Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Environment variables expansion fails if variable name contains dot/dash #57

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion QualityGatesPlugin/pom.xml
Expand Up @@ -34,7 +34,7 @@
<artifactId>quality-gates</artifactId>
<name>Quality Gates Plugin</name>
<url>https://wiki.jenkins-ci.org/display/JENKINS/Quality+Gates+Plugin</url>
<version>2.7-SNAPSHOT</version>
<version>2.7.2</version>
<description>Fails the build whenever the Quality Gates criteria in the Sonar analysis aren't met (the project Quality Gates status is different than "Passed")</description>
<packaging>hpi</packaging>

Expand Down
Expand Up @@ -14,8 +14,8 @@

public class JobConfigurationService {

private static final Pattern ENV_VARIABLE_WITH_BRACES_PATTERN = Pattern.compile( "(\\$\\{[a-zA-Z_]+\\})" );
private static final Pattern ENV_VARIABLE_WITHOUT_BRACES_PATTERN = Pattern.compile( "(\\$[a-zA-Z_]+)" );
private static final Pattern ENV_VARIABLE_WITH_BRACES_PATTERN = Pattern.compile( "(\\$\\{[a-zA-Z_]+[a-zA-Z0-9_\\.-]*\\})" );
private static final Pattern ENV_VARIABLE_WITHOUT_BRACES_PATTERN = Pattern.compile( "(\\$[a-zA-Z_]+[a-zA-Z0-9_\\.-]*)" );

public ListBoxModel getListOfSonarInstanceNames(GlobalConfig globalConfig) {
ListBoxModel listBoxModel = new ListBoxModel();
Expand Down
Expand Up @@ -5,21 +5,40 @@
import org.json.JSONObject;
import quality.gates.jenkins.plugin.QGException;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

public class QualityGateResponseParser {

public QualityGatesStatus getQualityGateResultFromJSON(String jsonString) throws QGException {
JSONArray resultArray = createJSONArrayFromString(jsonString);
import javax.print.attribute.standard.DateTimeAtCompleted;

JSONObject latestEventResult = getLatestEventResult(resultArray);
public class QualityGateResponseParser {

String gateStatus = getValueForJSONKey(latestEventResult, "n");
if (gateStatus.startsWith("Green"))
public QualityGatesStatus getQualityGateResultFromJSON(String jsonString, boolean isNewAPI) throws QGException {

JSONObject latestEventResult;
String fieldName;
if(isNewAPI) {
JSONObject resultObject = createJSONObjectFromString(jsonString);
latestEventResult = getLastestEventResultNewAPI(resultObject);
fieldName = "name";
} else {
JSONArray resultArray = createJSONArrayFromString(jsonString);
latestEventResult = getLatestEventResult(resultArray);
fieldName = "n";
}

String gateStatus = getValueForJSONKey(latestEventResult, fieldName);
if (gateStatus.startsWith("Green")) {
return QualityGatesStatus.GREEN;
}
if (gateStatus.startsWith("Orange"))
{
return QualityGatesStatus.ORANGE;
}
return QualityGatesStatus.RED;
}

Expand Down Expand Up @@ -48,6 +67,38 @@ protected JSONObject getLatestEventResult(JSONArray jsonArray) throws QGExceptio

return returnObject;
}

protected JSONObject getLastestEventResultNewAPI(JSONObject jsonObject) throws QGException {
JSONObject returnObject = createObjectWithStatusGreenNewAPI();

if(jsonObject.has("analyses")) {
JSONArray analyses = getJSONArrayFromObject(jsonObject,"analyses");

Date lastDate = new Date(0);

for( int i=0; i<analyses.length(); i++) {
JSONObject currentAnalysis = getJSONObjectFromArray(analyses, i);
if(currentAnalysis.has("events")) {
Date analysisDate = fromISO8601UTC(getValueForJSONKey(currentAnalysis, "date"));
if(lastDate.compareTo(analysisDate) < 0) {
JSONArray events = getJSONArrayFromObject(currentAnalysis,"events");
for (int j=0; j<events.length(); j++) {
JSONObject currentEvent = getJSONObjectFromArray(events,j);
if("QUALITY_GATE".equals(getValueForJSONKey(currentEvent, "category"))) {
lastDate = analysisDate;
returnObject = currentEvent;
break;
}
}
}
}
}
} else {
throw new QGException("The request returned an empty object");
}

return returnObject;
}

protected JSONObject createObjectWithStatusGreen() {
try {
Expand All @@ -60,6 +111,18 @@ protected JSONObject createObjectWithStatusGreen() {
throw new QGException(e);
}
}

protected JSONObject createObjectWithStatusGreenNewAPI() {
try {
JSONObject returnObject = new JSONObject();
returnObject.put("key", "1");
returnObject.put("category", "QUALITY_GATE");
returnObject.put("name", "Green");
return returnObject;
} catch (JSONException e) {
throw new QGException(e);
}
}

protected JSONObject getJSONObjectFromArray(JSONArray array, int index) throws QGException {
try {
Expand All @@ -68,6 +131,14 @@ protected JSONObject getJSONObjectFromArray(JSONArray array, int index) throws Q
throw new QGException("The request returned an empty array", e);
}
}

protected JSONArray getJSONArrayFromObject(JSONObject object, String key) throws QGException {
try {
return object.getJSONArray(key);
} catch (JSONException e) {
throw new QGException("The request returned an empty object", e);
}
}

protected String getValueForJSONKey(List<JSONObject> array, int index, String key) throws QGException {
try {
Expand All @@ -92,4 +163,25 @@ protected JSONArray createJSONArrayFromString(String jsonString) throws QGExcept
throw new QGException("There was a problem handling the JSON response " + jsonString, e);
}
}

protected JSONObject createJSONObjectFromString(String jsonString) throws QGException {
try {
return new JSONObject(jsonString);
} catch (JSONException e) {
throw new QGException("There was a problem handling the JSON response "+jsonString, e);
}
}

protected Date fromISO8601UTC(String dateStr) throws QGException {
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

df.setTimeZone(tz);
try {
return df.parse(dateStr);
} catch (ParseException e) {
throw new QGException("There was a problem parsing the JSON date "+dateStr, e);
}

}
}
Expand Up @@ -26,11 +26,24 @@ public QualityGatesProvider(QualityGateResponseParser qualityGateResponseParser,

public QualityGatesStatus getAPIResultsForQualityGates(JobConfigData jobConfigData, GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance) throws JSONException {
GlobalConfigDataForSonarInstance validatedData = sonarInstanceValidationService.validateData(globalConfigDataForSonarInstance);
String requesterResult = getRequesterResult(jobConfigData, validatedData);
return qualityGateResponseParser.getQualityGateResultFromJSON(requesterResult);

Float sonarVersion = sonarHttpRequester.getSonarQubeVersion(globalConfigDataForSonarInstance);

boolean useNewAPI = false;
if(sonarVersion >= 6.3) {
useNewAPI = true;
}

String requesterResult = getRequesterResult(jobConfigData, validatedData, useNewAPI);
return qualityGateResponseParser.getQualityGateResultFromJSON(requesterResult, useNewAPI);
}

public String getRequesterResult(JobConfigData jobConfigData, GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance) throws QGException {
return sonarHttpRequester.getAPIInfo(jobConfigData, globalConfigDataForSonarInstance);
public String getRequesterResult(JobConfigData jobConfigData, GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance, boolean useNewAPI) throws QGException {

if(useNewAPI) {
return sonarHttpRequester.getAPIInfoNew(jobConfigData, globalConfigDataForSonarInstance);
} else {
return sonarHttpRequester.getAPIInfo(jobConfigData, globalConfigDataForSonarInstance);
}
}
}
Expand Up @@ -23,18 +23,43 @@

public class SonarHttpRequester {

private static final String SONAR_API_VERSION = "/api/server/version";
private static final String SONAR_API_GATE = "/api/events?resource=%s&format=json&categories=Alert";
private static final String SONAR_API_GATE_NEW = "/api/project_analyses/search?project=%s&category=QUALITY_GATE";

private transient HttpClientContext context;

public SonarHttpRequester() {
}

public String getAPIInfo(JobConfigData projectKey, GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance) throws QGException {
String sonarApiGate = globalConfigDataForSonarInstance.getSonarUrl() + String.format(SONAR_API_GATE, projectKey.getProjectKey());

context = HttpClientContext.create();
public Float getSonarQubeVersion(GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance) throws QGException {
String sonarVersionAPI = globalConfigDataForSonarInstance.getSonarUrl() + SONAR_API_VERSION;

context = HttpClientContext.create();
CloseableHttpClient client = HttpClientBuilder.create().build();

HttpGet request = new HttpGet(sonarVersionAPI);
String result = executeGetRequest(client, request);
String[] resultTab = result.split("\\.");
if(resultTab.length >= 2) {
try {
int majorVersion = Integer.parseInt(resultTab[0]);
int minorVersion = Integer.parseInt(resultTab[1]);

return Float.parseFloat(majorVersion+"."+minorVersion);

} catch (NumberFormatException e) {
throw new QGException("Can't parse SonarQube version : "+result);
}
} else {
throw new QGException("Can't find major version of SonarQube : "+result);
}
}

private String getApiInfo(JobConfigData projectKey, GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance, String sonarApiGate) throws QGException {
context = HttpClientContext.create();
CloseableHttpClient client = HttpClientBuilder.create().build();

HttpPost loginHttpPost = new HttpPost(globalConfigDataForSonarInstance.getSonarUrl() + "/sessions/login");
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("login", globalConfigDataForSonarInstance.getUsername()));
Expand All @@ -46,6 +71,18 @@ public String getAPIInfo(JobConfigData projectKey, GlobalConfigDataForSonarInsta
HttpGet request = new HttpGet(String.format(sonarApiGate, projectKey.getProjectKey()));
return executeGetRequest(client, request);
}

public String getAPIInfo(JobConfigData projectKey, GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance) throws QGException {
String sonarApiGate = globalConfigDataForSonarInstance.getSonarUrl() + String.format(SONAR_API_GATE, projectKey.getProjectKey());

return getApiInfo(projectKey, globalConfigDataForSonarInstance, sonarApiGate);
}

public String getAPIInfoNew(JobConfigData projectKey, GlobalConfigDataForSonarInstance globalConfigDataForSonarInstance) throws QGException {
String sonarApiGate = globalConfigDataForSonarInstance.getSonarUrl() + String.format(SONAR_API_GATE_NEW, projectKey.getProjectKey());

return getApiInfo(projectKey, globalConfigDataForSonarInstance, sonarApiGate);
}

private String executeGetRequest(CloseableHttpClient client, HttpGet request) throws QGException {
CloseableHttpResponse response = null;
Expand Down