您好,登錄后才能下訂單哦!
這篇文章主要介紹“微服務(wù)需求與代碼管理的方法是什么”,在日常操作中,相信很多人在微服務(wù)需求與代碼管理的方法是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”微服務(wù)需求與代碼管理的方法是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
業(yè)務(wù)的簡(jiǎn)稱為demo,微服務(wù)架構(gòu)。N多個(gè)微服務(wù)。服務(wù)命名:業(yè)務(wù)簡(jiǎn)稱-應(yīng)用名稱-類型(demo-hello-service)。特性分支開(kāi)發(fā),版本分支發(fā)布。每個(gè)需求(任務(wù)/故事)對(duì)應(yīng)一個(gè)特性分支。每個(gè)發(fā)布(release)對(duì)應(yīng)一個(gè)版本分支。
1.需求與代碼管理
Jira作為需求和缺陷管理,采用Scrum開(kāi)發(fā)方法,jira中的項(xiàng)目名稱與業(yè)務(wù)簡(jiǎn)稱一致(demo)。Gitlab作為版本控制系統(tǒng),每個(gè)Group對(duì)應(yīng)一個(gè)業(yè)務(wù),每個(gè)微服務(wù)對(duì)應(yīng)一個(gè)代碼庫(kù)。
需求與代碼關(guān)聯(lián):在jira中創(chuàng)建一個(gè)任務(wù)/故事,關(guān)聯(lián)模塊后自動(dòng)在該模塊創(chuàng)建一個(gè)以ISSUE(任務(wù)/故事)ID的特性分支。此時(shí)的模塊等同于每個(gè)微服務(wù)的項(xiàng)目(代碼庫(kù))名稱。以下面圖中為例:我們?cè)赿emo項(xiàng)目中創(chuàng)建了一個(gè)模塊demo-hello-service,其實(shí)對(duì)應(yīng)的就是Gitlab代碼庫(kù)中demo組的demo-hello-service服務(wù)。
特性分支:創(chuàng)建好每個(gè)模塊后,就可以實(shí)現(xiàn)需求與代碼關(guān)聯(lián)。例如:我們?cè)贘ira項(xiàng)目demo中創(chuàng)建一個(gè)問(wèn)題,類型為故事(不受限制可為其他),重點(diǎn)是需要將改故事關(guān)聯(lián)到模塊(只有關(guān)聯(lián)到模塊,我們才能通過(guò)接口得知哪個(gè)問(wèn)題關(guān)聯(lián)的哪個(gè)代碼庫(kù))。
版本分支:當(dāng)特性分支開(kāi)發(fā)完成以及測(cè)試驗(yàn)證完成后,基于主干分支創(chuàng)建一個(gè)版本分支,然后將所有的特性分支合并到版本分支。此時(shí)可以通過(guò)Jira中創(chuàng)建一個(gè)發(fā)布版本,然后問(wèn)題關(guān)聯(lián)發(fā)布版本(此動(dòng)作表示該特性分支已經(jīng)通過(guò)驗(yàn)證,可以合并)。自動(dòng)完成版本分支的創(chuàng)建和特性分支到版本分支的合并請(qǐng)求。
2. 配置過(guò)程
需求與代碼庫(kù)關(guān)聯(lián),主要用到的工具鏈為: Jira + GitLab + Jenkins。Jira負(fù)責(zé)創(chuàng)建需求,配置webhook。Jenkins負(fù)責(zé)接收J(rèn)ira webhook請(qǐng)求,然后通過(guò)接口實(shí)現(xiàn)GitLab項(xiàng)目分支創(chuàng)建。
特性分支自動(dòng)化:當(dāng)我們?cè)趈ira上面創(chuàng)建了問(wèn)題,此時(shí)會(huì)通過(guò)Jira的webhook觸發(fā)對(duì)應(yīng)的Jenkins作業(yè),該Jenkins作業(yè)通過(guò)解析Jira webhook傳遞的數(shù)據(jù),找到問(wèn)題名稱和模塊名稱。調(diào)用GitlabAPI 項(xiàng)目查詢接口,根據(jù)模塊名稱找到代碼庫(kù)。調(diào)用GitLabAPI 分支創(chuàng)建接口,根據(jù)問(wèn)題名稱基于主干分支創(chuàng)建一個(gè)特性分支。任務(wù)結(jié)束。
版本分支自動(dòng)化:Jira創(chuàng)建發(fā)布版本,Issue關(guān)聯(lián)版本。自動(dòng)在gitlab代碼庫(kù)基于master創(chuàng)建版本分支,并開(kāi)啟特性分支到版本分支的合并請(qǐng)求。
2.1 準(zhǔn)備工作
在Jenkins, 創(chuàng)建一個(gè)Pipeline 作業(yè)并配置GenericTrigger 觸發(fā)器,接收J(rèn)iraWebhook數(shù)據(jù)。projectKey 參數(shù)表示Jira項(xiàng)目名稱,webHookData 參數(shù)為Jira webhook的所有數(shù)據(jù)。token 是觸發(fā)器的觸發(fā)token,這里默認(rèn)采用的作業(yè)名稱(作業(yè)名稱要唯一)。
triggers { GenericTrigger( causeString: 'Trigger By Jira Server -->>>>> Generic Cause', genericRequestVariables: [[key: 'projectKey', regexpFilter: '']], genericVariables: [[defaultValue: '', key: 'webHookData', regexpFilter: '', value: '$']], printContributedVariables: true, printPostContent: true, regexpFilterExpression: '', regexpFilterText: '', silentResponse: true, token: "${JOB_NAME}" )
在Jira項(xiàng)目中配置Webhook,勾選觸發(fā)事件填寫(xiě)觸發(fā)URL。http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=demo-jira-service&projectKey=${project.key} (這個(gè)地址是jenkins Generictrigger生成的,這里不做過(guò)多的介紹)
Jira webhook數(shù)據(jù)參考, 這些參數(shù)可以在Jenkinsfile中通過(guò)readJSON格式化,然后獲取值。
response = readJSON text: """${webHookData}""" println(response) //獲取webhook的事件類型 env.eventType = response["webhookEvent"]
{ "timestamp":1603087582648, "webhookEvent":"jira:issue_created", "issue_event_type_name":"issue_created", "user":Object{...}, "issue":{ "id":"10500", "self":"http://192.168.1.200:8050/rest/api/2/issue/10500", "key":"DEMO-2", "fields":{ "issuetype":{ "self":"http://192.168.1.200:8050/rest/api/2/issuetype/10001", "id":"10001", "description":"", "iconUrl":"http://192.168.1.200:8050/images/icons/issuetypes/story.svg", "name":"故事", "subtask":false }, "components":[ { "self":"http://192.168.1.200:8050/rest/api/2/component/10200", "id":"10200", "name":"demo-hello-service", "description":"demo-hello-service應(yīng)用" } ], "timespent":null, "timeoriginalestimate":null, "description":null, ... ... ...
2.2 封裝GitLab接口
Gitlab接口文檔:https://docs.gitlab.com/ce/api/README.html
共享庫(kù):src/org/devops/gitlab.groovy
package org.devops //封裝HTTP請(qǐng)求 def HttpReq(reqType,reqUrl,reqBody){ def gitServer = "http://gitlab.idevops.site/api/v4" withCredentials([string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) { result = httpRequest customHeaders: [[maskValue: true, name: 'PRIVATE-TOKEN', value: "${gitlabToken}"]], httpMode: reqType, contentType: "APPLICATION_JSON", consoleLogResponseBody: true, ignoreSslErrors: true, requestBody: reqBody, url: "${gitServer}/${reqUrl}" //quiet: true } return result } //更新文件內(nèi)容 def UpdateRepoFile(projectId,filePath,fileContent){ apiUrl = "projects/${projectId}/repository/files/${filePath}" reqBody = """{"branch": "master","encoding":"base64", "content": "${fileContent}", "commit_message": "update a new file"}""" response = HttpReq('PUT',apiUrl,reqBody) println(response) } //獲取文件內(nèi)容 def GetRepoFile(projectId,filePath){ apiUrl = "projects/${projectId}/repository/files/${filePath}/raw?ref=master" response = HttpReq('GET',apiUrl,'') return response.content } //創(chuàng)建倉(cāng)庫(kù)文件 def CreateRepoFile(projectId,filePath,fileContent){ apiUrl = "projects/${projectId}/repository/files/${filePath}" reqBody = """{"branch": "master","encoding":"base64", "content": "${fileContent}", "commit_message": "create a new file"}""" response = HttpReq('POST',apiUrl,reqBody) println(response) } //更改提交狀態(tài) def ChangeCommitStatus(projectId,commitSha,status){ commitApi = "projects/${projectId}/statuses/${commitSha}?state=${status}" response = HttpReq('POST',commitApi,'') println(response) return response } //獲取項(xiàng)目ID def GetProjectID(repoName='',projectName){ projectApi = "projects?search=${projectName}" response = HttpReq('GET',projectApi,'') def result = readJSON text: """${response.content}""" for (repo in result){ // println(repo['path_with_namespace']) if (repo['path'] == "${projectName}"){ repoId = repo['id'] println(repoId) } } return repoId } //刪除分支 def DeleteBranch(projectId,branchName){ apiUrl = "/projects/${projectId}/repository/branches/${branchName}" response = HttpReq("DELETE",apiUrl,'').content println(response) } //創(chuàng)建分支 def CreateBranch(projectId,refBranch,newBranch){ try { branchApi = "projects/${projectId}/repository/branches?branch=${newBranch}&ref=${refBranch}" response = HttpReq("POST",branchApi,'').content branchInfo = readJSON text: """${response}""" } catch(e){ println(e) } //println(branchInfo) } //創(chuàng)建合并請(qǐng)求 def CreateMr(projectId,sourceBranch,targetBranch,title,assigneeUser=""){ try { def mrUrl = "projects/${projectId}/merge_requests" def reqBody = """{"source_branch":"${sourceBranch}", "target_branch": "${targetBranch}","title":"${title}","assignee_id":"${assigneeUser}"}""" response = HttpReq("POST",mrUrl,reqBody).content return response } catch(e){ println(e) } } //搜索分支 def SearchProjectBranches(projectId,searchKey){ def branchUrl = "projects/${projectId}/repository/branches?search=${searchKey}" response = HttpReq("GET",branchUrl,'').content def branchInfo = readJSON text: """${response}""" def branches = [:] branches[projectId] = [] if(branchInfo.size() ==0){ return branches } else { for (branch in branchInfo){ //println(branch) branches[projectId] += ["branchName":branch["name"], "commitMes":branch["commit"]["message"], "commitId":branch["commit"]["id"], "merged": branch["merged"], "createTime": branch["commit"]["created_at"]] } return branches } } //允許合并 def AcceptMr(projectId,mergeId){ def apiUrl = "projects/${projectId}/merge_requests/${mergeId}/merge" HttpReq('PUT',apiUrl,'') }
2.3 共享庫(kù)配置
到此,關(guān)于“微服務(wù)需求與代碼管理的方法是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。