Added code to fill in menus for the bug report form and display it when placing a marker.

This commit is contained in:
Jamie Greunbaum
2024-05-23 01:36:00 -04:00
parent 5c37903872
commit 64f6193701
11 changed files with 447 additions and 118 deletions
+10 -4
View File
@@ -1,7 +1,7 @@
class_name BugbotServerAPI
extends Resource
enum BugbotServerError { OK, THREAD_NULL, THREAD_BUSY }
enum BugbotServerError { OK, THREAD_NULL, THREAD_BUSY, API_RESPONSE_ERROR }
var __bugbot_server_thread : Thread
@@ -41,8 +41,11 @@ func __connect_to_server(http_client:HTTPClient, default_server:String) -> int:
var server_and_port : PackedStringArray = full_server.rsplit(":",true,1)
var server : String = server_and_port[0]
var port : int = int(server_and_port[1])
var error : int = http_client.connect_to_host(server if port > 0 else full_server, port if port > 0 else -1)
return error
http_client.connect_to_host(server if port > 0 else full_server, port if port > 0 else -1)
while http_client.get_status() == HTTPClient.STATUS_CONNECTING or http_client.get_status() == HTTPClient.STATUS_RESOLVING:
http_client.poll()
return http_client.get_status()
func __get_http_client_chunk_response(http_client:HTTPClient) -> String:
if http_client.has_response():
@@ -66,6 +69,9 @@ func __start_thread_with_callback(thread_function:Callable) -> int:
__bugbot_server_thread.start(thread_function)
return BugbotServerError.OK
func __validate_server_response(_response:Variant) -> int:
return Error.OK
func _current_server_api() -> String:
return ""
@@ -73,7 +79,7 @@ func _current_server_api() -> String:
func __build_url_string(_api_suffix:String) -> String:
return ""
func __create_header_data(mime_type:String, api_key:String, content_length:int = -1) -> Array:
func __create_header_data(content_length:int = -1) -> Array:
return []
+156 -113
View File
@@ -9,6 +9,11 @@ const DEFAULT_REPO_NAME : StringName = &"ProjectName"
const DEFAULT_API_KEY : StringName = &"0123456789abcdef0123456789abcdef01234567"
const DEFAULT_BUG_LABEL : StringName = &"Kind/Bug"
const DEFAULT_STATUS_LABEL : StringName = &"Status/Need More Info"
const DEFAULT_VERSION_LABEL_PREFIX : StringName = &"Version/"
const DEFAULT_HARDWARE_LABEL_PREFIX : StringName = &"Hardware/"
const DEFAULT_OS_LABEL_PREFIX : StringName = &"OS/"
const DEFAULT_COMPONENT_LABEL_PREFIX : StringName = &"Component/"
const DEFAULT_PRIORITY_LABEL_PREFIX : StringName = &"Priority/"
const UNRESOLVED_TAG : StringName = &"Status/Unresolved"
const IN_PROGRESS_TAG : StringName = &"Status/In Progress"
@@ -20,8 +25,7 @@ func _return_list_of_bugs(callback:Callable) -> int:
return __start_thread_with_callback(__return_list_of_bugs_thread.bind(callback))
func _prepare_form(callback:Callable) -> int:
print(_current_server_api(), " has not yet implemented this functionality.")
return BugbotServerError.OK
return __start_thread_with_callback(__prepare_form_thread.bind(callback))
func _send_form_data(callback:Callable) -> int:
return __start_thread_with_callback(__send_form_data_thread.bind(callback))
@@ -29,136 +33,161 @@ func _send_form_data(callback:Callable) -> int:
func __return_list_of_bugs_thread(callback:Callable) -> void:
var http_client : HTTPClient = HTTPClient.new()
var error : int = __connect_to_server(http_client, DEFAULT_SERVER)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_CONNECTING or http_client.get_status() == HTTPClient.STATUS_RESOLVING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_CONNECTED)
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.")
return
var api_url : String = __build_url_string("issues")
api_url += "?state=all&labels=" + ProjectSettings.get_setting("bugbot/reporting/gitea/bug_label", DEFAULT_BUG_LABEL).uri_encode()
var header_data : Array = __create_header_data("application/json", ProjectSettings.get_setting("bugbot/reporting/gitea/API_key", DEFAULT_API_KEY))
error = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
var header_data : Array = __create_header_data()
var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED)
var response_string : String = __get_http_client_chunk_response(http_client)
var response_array : Array
var response_data := JSON.parse_string(response_string)
if __validate_server_response(response_data) != Error.OK:
return
# If the response is an array, we can make the assumption that this is
# a list of returned bugs.
if response_data is Array:
var resolved_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/resolved_statuses")
var in_progress_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/in_progress_statuses")
var unresolved_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/unresolved_statuses")
var show_resolved : bool = ProjectSettings.get_setting("bugbot/markers/resolved/show_resolved_bugs")
var show_in_progress : bool = ProjectSettings.get_setting("bugbot/markers/in_progress/show_in_progress_bugs")
var show_unresolved : bool = ProjectSettings.get_setting("bugbot/markers/unresolved/show_unresolved_bugs")
for bug_in:Dictionary in response_data:
var bug : BugbotBugData = BugbotBugData.new()
var bug_labels : Array = []
var resolved_tag_found : bool = false
var in_progress_tag_found : bool = false
var unresolved_tag_found : bool = false
# Find which resolution statuses apply to this bug.
bug.is_open = (bug_in["state"] == "open")
if not bug.is_open:
resolved_tag_found = true
else:
for labels:Dictionary in bug_in["labels"]:
bug_labels.append(labels["name"] as String)
for label:String in resolved_labels:
if bug_labels.has(label): resolved_tag_found = true
for label:String in in_progress_labels:
if bug_labels.has(label): in_progress_tag_found = true
for label:String in unresolved_labels:
if bug_labels.has(label): unresolved_tag_found = true
# Figure out which resolution tag to prioritise, and whether we should show the marker.
var show_marker : bool
if resolved_tag_found:
bug.resolution = RESOLVED_TAG
show_marker = show_resolved
elif in_progress_tag_found:
bug.resolution = IN_PROGRESS_TAG
show_marker = show_in_progress
elif unresolved_tag_found or unresolved_labels.is_empty():
bug.resolution = UNRESOLVED_TAG
show_marker = show_unresolved
if not show_marker: continue
bug.id = bug_in["id"]
bug.title = bug_in["title"]
bug.body = bug_in["body"]
bug.component = &"Unused"
bug.platform = &"Unused"
bug.operating_system = &"Unused"
bug.severity = "Severity will go here."
bug.status = bug_in["state"]
bug.duplicate_of = -1
bug.map_name = "Map name will go here."
bug.marker_location = "Marker location will go here."
response_array.append(bug)
elif response_data is Dictionary:
# If the response is a dictionary and not an array, make the assumption
# that this is because the response was an error code.
var error_data : BugbotErrorData = BugbotErrorData.new()
error_data.code = 1
error_data.message = response_data["message"]
error_data.url = response_data["url"]
response_array.append(error_data)
printerr(error_data.message)
var bug_array : Array
var resolved_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/resolved_statuses")
var in_progress_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/in_progress_statuses")
var unresolved_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/unresolved_statuses")
callback.call_deferred(response_array)
var show_resolved : bool = ProjectSettings.get_setting("bugbot/markers/resolved/show_resolved_bugs")
var show_in_progress : bool = ProjectSettings.get_setting("bugbot/markers/in_progress/show_in_progress_bugs")
var show_unresolved : bool = ProjectSettings.get_setting("bugbot/markers/unresolved/show_unresolved_bugs")
for bug_in:Dictionary in response_data:
var bug : BugbotBugData = BugbotBugData.new()
var bug_labels : Array = []
var resolved_tag_found : bool = false
var in_progress_tag_found : bool = false
var unresolved_tag_found : bool = false
# Find which resolution statuses apply to this bug.
bug.is_open = (bug_in["state"] == "open")
if not bug.is_open:
resolved_tag_found = true
else:
for labels:Dictionary in bug_in["labels"]:
bug_labels.append(labels["name"] as String)
for label:String in resolved_labels:
if bug_labels.has(label): resolved_tag_found = true
for label:String in in_progress_labels:
if bug_labels.has(label): in_progress_tag_found = true
for label:String in unresolved_labels:
if bug_labels.has(label): unresolved_tag_found = true
# Figure out which resolution tag to prioritise, and whether we should show the marker.
var show_marker : bool
if resolved_tag_found:
bug.resolution = RESOLVED_TAG
show_marker = show_resolved
elif in_progress_tag_found:
bug.resolution = IN_PROGRESS_TAG
show_marker = show_in_progress
elif unresolved_tag_found or unresolved_labels.is_empty():
bug.resolution = UNRESOLVED_TAG
show_marker = show_unresolved
if not show_marker: continue
bug.id = bug_in["id"]
bug.title = bug_in["title"]
bug.body = bug_in["body"]
bug.component = &"Unused"
bug.platform = &"Unused"
bug.operating_system = &"Unused"
bug.severity = "Severity will go here."
bug.status = bug_in["state"]
bug.duplicate_of = -1
bug.map_name = "Map name will go here."
bug.marker_location = "Marker location will go here."
bug_array.append(bug)
callback.call_deferred(bug_array)
__bugbot_server_thread.call_deferred("wait_to_finish")
func __prepare_form_thread(callback:Callable) -> void:
var http_client : HTTPClient = HTTPClient.new()
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.")
return
# Pull a list of issue labels so we can get the ones we care about.
var api_url : String = __build_url_string("labels")
var header_data : Array = __create_header_data()
var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED)
var response_string : String = __get_http_client_chunk_response(http_client)
var response_data := JSON.parse_string(response_string)
if __validate_server_response(response_data) != Error.OK:
return
var version_tags : Array
var hardware_tags : Array
var os_tags : Array
var component_tags : Array
var priority_tags : Array
var version_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/version_label_prefix", DEFAULT_VERSION_LABEL_PREFIX)
var hardware_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/hardware_label_prefix", DEFAULT_HARDWARE_LABEL_PREFIX)
var os_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/os_label_prefix", DEFAULT_OS_LABEL_PREFIX)
var component_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/component_label_prefix", DEFAULT_COMPONENT_LABEL_PREFIX)
var priority_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/priority_label_prefix", DEFAULT_PRIORITY_LABEL_PREFIX)
for label_in:Dictionary in response_data:
if version_prefix and label_in["name"].begins_with(version_prefix):
version_tags.append(label_in)
if hardware_prefix and label_in["name"].begins_with(hardware_prefix):
hardware_tags.append(label_in)
if os_prefix and label_in["name"].begins_with(os_prefix):
os_tags.append(label_in)
if component_prefix and label_in["name"].begins_with(component_prefix):
component_tags.append(label_in)
if priority_prefix and label_in["name"].begins_with(priority_prefix):
priority_tags.append(label_in)
version_tags.sort_custom(func(a,b):return a["id"] < b["id"])
hardware_tags.sort_custom(func(a,b):return a["id"] < b["id"])
os_tags.sort_custom(func(a,b):return a["id"] < b["id"])
component_tags.sort_custom(func(a,b):return a["id"] < b["id"])
priority_tags.sort_custom(func(a,b): return a["id"] < b["id"])
var tag_lists : Array = [version_tags, hardware_tags, os_tags, component_tags, priority_tags]
callback.call_deferred(tag_lists)
__bugbot_server_thread.call_deferred("wait_to_finish")
func __send_form_data_thread(callback:Callable) -> void:
var http_client : HTTPClient = HTTPClient.new()
var error : int = __connect_to_server(http_client, DEFAULT_SERVER)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_CONNECTING or http_client.get_status() == HTTPClient.STATUS_RESOLVING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_CONNECTED)
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.")
return
var api_url : String = __build_url_string("labels")
var api_key : String = ProjectSettings.get_setting("bugbot/reporting/gitea/API_key", DEFAULT_API_KEY)
var header_data : Array = __create_header_data("application/json", api_key)
error = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
var header_data : Array = __create_header_data()
var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED)
var response_string : String = __get_http_client_chunk_response(http_client)
var response_array : Array
var response_data := JSON.parse_string(response_string)
if response_data is Array:
# If the response is an array, we can make the assumption that this is
# a list of returned bugs.
var bug_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/bug_label", DEFAULT_BUG_LABEL)
var status_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/default_status_label", DEFAULT_STATUS_LABEL)
for label_in:Dictionary in response_data:
if label_in["name"] == bug_label or label_in["name"] == status_label:
response_array.append(label_in["id"])
elif response_data is Dictionary:
# If the response is a dictionary and not an array, make the assumption
# that this is because the response was an error code.
var error_data : BugbotErrorData = BugbotErrorData.new()
error_data.code = 1
error_data.message = response_data["message"]
error_data.url = response_data["url"]
response_array.append(error_data)
printerr(error_data.message)
if __validate_server_response(response_data) != Error.OK:
return
var response_array : Array
var bug_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/bug_label", DEFAULT_BUG_LABEL)
var status_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/default_status_label", DEFAULT_STATUS_LABEL)
for label_in:Dictionary in response_data:
if label_in["name"] == bug_label or label_in["name"] == status_label:
response_array.append(label_in["id"])
api_url = __build_url_string("issues")
var post_data : Dictionary = {
@@ -167,7 +196,7 @@ func __send_form_data_thread(callback:Callable) -> void:
"labels": response_array,
}
var post_data_string : String = JSON.stringify(post_data)
header_data = __create_header_data("application/json", api_key, post_data_string.length())
header_data = __create_header_data(post_data_string.length())
error = http_client.request(HTTPClient.METHOD_POST, api_url, header_data, post_data_string)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
@@ -191,12 +220,26 @@ func __build_url_string(_api_suffix:String) -> String:
ProjectSettings.get_setting("bugbot/reporting/gitea/repo_name", DEFAULT_REPO_NAME) + \
"/" + _api_suffix
func __create_header_data(mime_type:String, api_key:String, content_length:int = -1) -> Array:
func __create_header_data(content_length:int = -1) -> Array:
var header : Array = [
"User-Agent: Pirulo/1.0 (Godot)",
"Accept: " + mime_type,
"Content-Type: " + mime_type,
"Accept: application/json",
]
if api_key: header.append("Authorization: token " + api_key)
if content_length >= 0: header.append("Content-Length: " + String.num_uint64(content_length))
header.append("Authorization: token " + ProjectSettings.get_setting("bugbot/reporting/gitea/API_key", DEFAULT_API_KEY))
if content_length >= 0:
header.append("Content-Type: application/json")
header.append("Content-Length: " + String.num_uint64(content_length))
return header
func __validate_server_response(_response:Variant) -> int:
# If the response is a dictionary and not an array, make the assumption
# that this is because the response was an error code.
if _response is Dictionary:
var error_data : BugbotErrorData = BugbotErrorData.new()
error_data.code = 1
error_data.message = _response["message"]
error_data.url = _response["url"]
printerr(error_data.message)
__bugbot_server_thread.call_deferred("wait_to_finish")
return Error.FAILED
return Error.OK