我们有几个JIRA问题,有超过1000个重复,虚假,类似垃圾邮件的评论。我们怎样才能快速删除它们?
背景:
我们在活动目录(Exchange)中禁用了用户,但未禁用JIRA,因此JIRA一直尝试通过电子邮件向他们发送更新。电子邮件服务器给出了退回消息,JIRA尽职地将其记录到任务中,这导致它发送另一个更新,并且反馈循环诞生了。
消息的格式为:
Delivery has failed to these recipients or groups:
mail@example.com<mail@example.com>
The e-mail address you entered couldn't be found. Please check the recipient's e-mail address and try to resend the message. If the problem continues, please contact your helpdesk.
Diagnostic information for administrators:
Generating server: emailserver.example.com
user@example.com
#550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ##
Original message headers:
Received: from jiraserver.example.com (10.0.0.999) by emailserver.example.com (10.0.0.999)
with Microsoft SMTP Server id nn.n.nnn.n; Mon, 13 Jun 2016 15:57:04 -0500
Date: Mon, 13 Jun 2016 15:57:03 -0500
Our research没有使用购买的插件,例如Script Runner或“黑客”数据库,这是我们想要避免的。
注意:
我们提出了一个解决方案,并在此发帖分享。
答案 0 :(得分:1)
通过Chrome JavaScript控制台使用JIRA REST API。
背景:
我们并不想为我们希望的孤立事件编写完整的应用程序。我们原计划使用PowerShell的Invoke-WebRequest。但是,身份验证证明是一项挑战。 API支持Basic Authentication,虽然它只是recommended when using SSL,但我们并未将其用于内部服务器。此外,我们的初始测试导致401错误(可能是由于错误)。
但是,API还支持基于cookie的身份验证,因此只要您从具有有效JIRA会话的浏览器生成请求,它就可以正常运行。我们选择了这种方法。
解决方案详情:
首先,查找并查看相关评论和问题ID:
SELECT * FROM jira..jiraaction WHERE actiontype = 'comment' AND actionbody LIKE '%RESOLVER.ADR.RecipNotFound%';
这可能是一个慢查询,具体取决于您的JIRA数据的大小。它似乎在issueid
上编入索引,因此如果您知道,请指定它。另外,为此查询添加其他条件,以便它仅表示您要删除的注释。
以下解决方案是针对单个问题发表的评论,但可以扩展一些额外的JavaScript以支持多个问题。
我们需要在Chrome JavaScript控制台中使用的评论ID列表。有用的格式是以逗号分隔的字符串列表,您可以按如下方式创建:
SELECT '"' + CONVERT(VARCHAR(50),ID) + '", ' FROM jira..jiraaction WHERE actiontype = 'comment' AND actionbody LIKE '%RESOLVER.ADR.RecipNotFound%' AND issueid = @issueid FOR XML PATH('')
(这不一定是concatenate strings in SQL的最佳方式,但它很简单并且可以用于此目的。)
现在,打开一个新的浏览器会话并对您的JIRA实例进行身份验证。我们使用的是Chrome,但任何带有JavaScript控制台的浏览器都应该这样做。
获取该查询生成的字符串并将其放在JavaScript控制台中,如下所示:
CommentIDs = [StringFromSQL];
您需要手动修剪尾随逗号(或调整上述查询以便为您执行此操作)。它看起来像这样:
CommentIDs = ["1234", "2345"];
运行该命令时,您将创建一个包含所有这些注释ID的JavaScript数组。
现在我们到达了技术的核心。我们将循环遍历该数组的内容,并使用XMLHttpRequest(通常缩写为XHR)对REST API进行新的AJAX调用。 (还有jQuery option。)
for (let s of CommentIDs) {let r = new XMLHttpRequest; r.open("DELETE","http://jira.example.com/rest/api/2/issue/11111/comment/"+s,true); r.send();}
你必须更换&#34; 11111&#34;与相关的问题ID。您可以为多个问题ID重复此操作,或者您可以构建一个多维数组和一个更高级的循环。
这不优雅。它没有任何错误处理,但您可以使用Chrome JavaScript API监控进度。
答案 1 :(得分:1)
我会使用jira-python脚本或ScriptRunner groovy脚本。即使是一次性批量更新,因为它更容易测试并且不需要数据库访问。
很高兴它对你有用!
答案 2 :(得分:0)
我创建了一个python脚本,以删除有关特定Jira问题的所有注释。 它使用了Jira的API。
'''
This script removes all comments from a specified jira issue
Please provide Jira-Issue-Key/Id, Jira-URL, Username, PAssword in the variables below.
'''
import sys
import json
import requests
import urllib3
# Jira Issue Key or Id where comments are deleted from
JIRA_ISSUE_KEY = 'TST-123'
# URL to Jira
URL_JIRA = 'https://jira.contoso.com'
# Username with enough rights to delete comments
JIRA_USERNAME = 'admin'
# Password to Jira User
JIRA_PASSWORD = 'S9ev6ZpQ4sy2VFH2_bjKKQAYRUlDfW7ujNnrIq9Lbn5w'
''' ----- ----- Do not change anything below ----- ----- '''
# Ignore SSL problem (certificate) - self signed
urllib3.disable_warnings()
# get issue comments:
# https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-comment-get
URL_GET_COMMENT = '{0}/rest/api/latest/issue/{1}/comment'.format(URL_JIRA, JIRA_ISSUE_KEY)
# delete issue comment:
# https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-comment-id-delete
URL_DELETE_COMMENT = '{0}/rest/api/2/issue/{1}/comment/{2}'
def user_yesno():
''' Asks user for input yes or no, responds with boolean '''
allowed_response_yes = {'yes', 'y'}
allowed_response_no = {'no', 'n'}
user_response = input().lower()
if user_response in allowed_response_yes:
return True
elif user_response in allowed_response_no:
return False
else:
sys.stdout.write("Please respond with 'yes' or 'no'")
return False
# get jira comments
RESPONSE = requests.get(URL_GET_COMMENT, verify=False, auth=(JIRA_USERNAME, JIRA_PASSWORD))
# check if http response is OK (200)
if RESPONSE.status_code != 200:
print('Exit-101: Could not connect to api [HTTP-Error: {0}]'.format(RESPONSE.status_code))
sys.exit(101)
# parse response to json
JSON_RESPONSE = json.loads(RESPONSE.text)
# get user confirmation to delete all comments for issue
print('You want to delete {0} comments for issue {1}? (yes/no)' \
.format(len(JSON_RESPONSE['comments']), JIRA_ISSUE_KEY))
if user_yesno():
for jira_comment in JSON_RESPONSE['comments']:
print('Deleting Jira comment {0}'.format(jira_comment['id']))
# send delete request
RESPONSE = requests.delete(
URL_DELETE_COMMENT.format(URL_JIRA, JIRA_ISSUE_KEY, jira_comment['id']),
verify=False, auth=(JIRA_USERNAME, JIRA_PASSWORD))
# check if http response is No Content (204)
if RESPONSE.status_code != 204:
print('Exit-102: Could not connect to api [HTTP-Error: {0}; {1}]' \
.format(RESPONSE.status_code, RESPONSE.text))
sys.exit(102)
else:
print('User abort script...')
源代码控制:https://gist.github.com/fty4/151ee7070f2a3f9da2cfa9b1ee1c132d