如何通过Groovy Script实现JIRA用户创建/移除自动化?
用Groovy脚本实现JIRA用户创建/移除自动化
前置条件
- 已安装ScriptRunner for JIRA插件(这是运行Groovy脚本的核心工具)
- 拥有JIRA系统管理员权限,以及ScriptRunner的脚本编辑权限
- 工单项目已配置必要自定义字段:
用户名:存储待操作的用户账号操作类型:单选字段,选项为「创建用户」/「移除用户」所需角色:存储待分配的项目角色(可选,仅创建用户时用)
- 工作流中已存在「已审批」状态,且对应过渡可添加后置函数
实现步骤
1. 添加工作流后置函数
进入目标工单项目的工作流配置页面,找到转入「已审批」状态的过渡,添加ScriptRunner提供的Script Post Function。
2. 编写Groovy核心脚本
以下脚本可直接复用,需根据实际环境调整字段名称、过渡ID等参数:
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.user.UserManager import com.atlassian.jira.bc.user.UserService import com.atlassian.jira.security.roles.ProjectRoleManager import com.atlassian.jira.bc.issue.IssueService.TransitionService // 获取JIRA核心组件实例 def userManager = ComponentAccessor.getUserManager() def userService = ComponentAccessor.getComponent(UserService) def projectRoleManager = ComponentAccessor.getComponent(ProjectRoleManager) def transitionService = ComponentAccessor.getComponent(TransitionService) def commentManager = ComponentAccessor.getCommentManager() def log = log def issue = issue // 从工单提取关键字段值(替换为你的实际字段名称) def username = issue.getCustomFieldValue(ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("用户名")[0])?.toString() def actionType = issue.getCustomFieldValue(ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("操作类型")[0])?.toString() def roleName = issue.getCustomFieldValue(ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("所需角色")[0])?.toString() // 校验必填字段 if (!username || !actionType) { log.error("工单${issue.key}缺少必填字段:用户名/操作类型") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "操作失败:缺少必填字段(用户名/操作类型)", false) return } // 处理用户创建逻辑 if (actionType == "创建用户") { def existingUser = userManager.getUserByName(username) if (existingUser) { log.info("用户${username}已存在,跳过创建") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "用户${username}已存在,无需重复创建", false) closeIssue(issue, transitionService) return } // 构造创建请求(可根据需求补充邮箱、显示名等) def createRequest = userService.newCreateUserRequest(ComponentAccessor.jiraAuthenticationContext.loggedInUser) .setUsername(username) .setPassword("Temp@123") // 建议后续改为自动生成并发送重置邮件 .setDisplayName(username) .setEmailAddress("${username}@yourdomain.com") .setNotifyUser(true) // 开启后会给用户发密码重置邮件 def validationResult = userService.validateCreateUser(createRequest) if (validationResult.isValid()) { def newUser = userService.createUser(validationResult) log.info("成功创建用户:${username}") // 分配项目角色(如果指定了角色) if (roleName) { def projectRole = projectRoleManager.getProjectRole(roleName) if (projectRole) { projectRoleManager.addUserToProjectRole(newUser, projectRole, issue.projectObject) log.info("已为用户${username}分配角色:${roleName}") } else { log.error("未找到项目角色:${roleName}") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "警告:未找到指定项目角色${roleName}", false) } } commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "已成功创建用户${username},并分配角色${roleName ?: '无'}", false) closeIssue(issue, transitionService) } else { def errorMsg = validationResult.errorCollection.getErrorMessages().join("; ") log.error("创建用户${username}失败:${errorMsg}") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "创建用户失败:${errorMsg}", false) } } // 处理用户移除逻辑 else if (actionType == "移除用户") { def targetUser = userManager.getUserByName(username) if (!targetUser) { log.error("用户${username}不存在,无法移除") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "操作失败:用户${username}不存在", false) return } def deleteValidation = userService.validateDeleteUser(ComponentAccessor.jiraAuthenticationContext.loggedInUser, targetUser) if (deleteValidation.isValid()) { userService.deleteUser(deleteValidation) log.info("成功移除用户:${username}") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "已成功移除用户${username}", false) closeIssue(issue, transitionService) } else { def errorMsg = deleteValidation.errorCollection.getErrorMessages().join("; ") log.error("移除用户${username}失败:${errorMsg}") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "移除用户失败:${errorMsg}", false) } } // 处理无效操作类型 else { log.error("工单${issue.key}操作类型无效:${actionType}") commentManager.create(issue, ComponentAccessor.jiraAuthenticationContext.loggedInUser, "操作失败:无效的操作类型", false) } // 封装关闭工单的方法 def closeIssue(issue, transitionService) { // 替换为你的工单项目中「关闭」操作的过渡ID def closeTransitionId = 6 def transitionRequest = transitionService.newTransitionValidationRequest(ComponentAccessor.jiraAuthenticationContext.loggedInUser, issue.id) transitionRequest.setTransitionId(closeTransitionId) def validationResult = transitionService.validate(transitionRequest) if (validationResult.isValid()) { transitionService.execute(validationResult) log.info("已关闭工单${issue.key}") } else { log.error("关闭工单${issue.key}失败:${validationResult.errorCollection}") } }
3. 自定义调整与测试
- 替换脚本中的自定义字段名称为项目实际使用的字段名(用字段ID替代名称更稳定,可通过
getCustomFieldObjectsById("字段ID")获取) - 修改
closeTransitionId为工单项目中「关闭」操作的实际过渡ID(可在工作流配置中查看) - 测试阶段使用测试账号和测试工单验证,避免影响生产环境
- 建议将临时密码改为自动生成逻辑,比如用
UUID.randomUUID().toString().substring(0,8)生成随机密码
关键注意事项
- 脚本运行的上下文用户需拥有创建/删除用户、分配项目角色、修改工单状态的权限
- 建议添加全局异常捕获,避免脚本执行中断导致工单停滞
- 定期查看ScriptRunner日志,排查执行失败的工单
内容的提问来源于stack exchange,提问作者CH BHARATH KUMAR
相关产品推荐
相关产品推荐

