1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-12 10:55:20 +02:00

Merge branch 'master' into pr/adjustConfigKeySetsInSteps

This commit is contained in:
Oliver Nocon 2018-10-31 10:43:38 +01:00 committed by GitHub
commit 2dbfeed813
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 427 additions and 8 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -0,0 +1,77 @@
# githubPublishRelease
## Description
This step creates a tag in your GitHub repository together with a release.
The release can be filled with text plus additional information like:
* Closed pull request since last release
* Closed issues since last release
* link to delta information showing all commits since last release
The result looks like
![Example release](../images/githubRelease.png)
## Prerequisites
You need to create a personal access token within GitHub and add this to the Jenkins credentials store.
Please see [GitHub documentation for details about creating the personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/).
## Example
Usage of pipeline step:
```groovy
githubPublishRelease script: this, releaseBodyHeader: "**This is the latest success!**<br />"
```
## Parameters
| parameter | mandatory | default | possible values |
| ----------|-----------|---------|-----------------|
|script|yes|||
|addClosedIssues|no|`false`||
|addDeltaToLastRelease|no|`false`||
|customFilterExtension|no|``||
|excludeLabels|no|<ul><li>`duplicate`</li><li>`invalid`</li><li>`question`</li><li>`wontfix`</li></ul>||
|githubApiUrl|no|`//https://api.github.com`||
|githubOrg|yes|`script.commonPipelineEnvironment.getGitFolder()`||
|githubRepo|yes|`script.commonPipelineEnvironment.getGitRepo()`||
|githubServerUrl|no|`https://github.com`||
|githubTokenCredentialsId|yes|||
|releaseBodyHeader|no|||
|version|yes|`script.commonPipelineEnvironment.getArtifactVersion()`||
### Details:
* `script` defines the global script environment of the Jenkinsfile run. Typically `this` is passed to this parameter. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for storing the measured duration.
* All GitHub related properties allow you to overwrite the default behavior of identifying e.g. GitHub organization, GitHub repository.
* `version` defines the version number which will be written as tag as well as release name
* By defining the `releaseBodyHeader` you can specify the content which will appear for the release
* If you set `addClosedIssues` to `true`, a list of all closed issues and merged pull-requests since the last release will added below the `releaseBodyHeader`
* If you set `addDeltaToLastRelease` to `true`, a link will be added to the relese information that brings up all commits since the last release.
* By passing the parameter `customFilterExtension` it is possible to pass additional filter criteria for retrieving closed issues since the last release. Additional criteria could be for example specific `label`, or `filter` according to [GitHub API documentation](https://developer.github.com/v3/issues/).
* It is possible to exclude issues with dedicated labels using parameter `excludeLabels`. Usage is like `excludeLabels: ['label1', 'label2']`
## Step configuration
We recommend to define values of step parameters via [config.yml file](../configuration.md).
In following sections the configuration is possible:
| parameter | general | step | stage |
| ----------|-----------|---------|-----------------|
|script||||
|addClosedIssues||X|X|
|addDeltaToLastRelease||X|X|
|customFilterExtension||X|X|
|excludeLabels||X|X|
|githubApiUrl|X|X|X|
|githubOrg||X|X|
|githubRepo||X|X|
|githubServerUrl|X|X|X|
|githubTokenCredentialsId|X|X|X|
|releaseBodyHeader||X|X|
|version||X|X|

View File

@ -12,6 +12,7 @@ nav:
- dockerExecute: steps/dockerExecute.md
- dockerExecuteOnKubernetes: steps/dockerExecuteOnKubernetes.md
- durationMeasure: steps/durationMeasure.md
- githubPublishRelease: steps/githubPublishRelease.md
- gaugeExecuteTests: steps/gaugeExecuteTests.md
- handlePipelineStepErrors: steps/handlePipelineStepErrors.md
- healthExecuteCheck: steps/healthExecuteCheck.md

View File

@ -12,6 +12,8 @@ general:
from: 'origin/master'
to: 'HEAD'
format: '%b'
githubApiUrl: 'https://api.github.com'
githubServerUrl: 'https://github.com'
gitSshKeyCredentialsId: '' #needed to allow sshagent to run with local ssh key
jenkinsKubernetes:
jnlpAgent: 's4sdk/jenkins-agent-k8s:latest'
@ -140,6 +142,15 @@ steps:
workspace: '**/*.*'
stashExcludes:
workspace: 'nohup.out'
githubPublishRelease:
addClosedIssues: false
addDeltaToLastRelease: false
customFilterExtension: ''
excludeLabels:
- 'duplicate'
- 'invalid'
- 'question'
- 'wontfix'
gaugeExecuteTests:
buildTool: 'maven'
dockerEnvVars:

View File

@ -44,7 +44,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(true)
jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
cmUtils: cm,
changeManagement: [
type: 'SOLMAN',
@ -69,7 +69,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false)
jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
cmUtils: cm,
changeManagement: [type: 'SOLMAN',
endpoint: 'https://example.org/cm'])
@ -80,7 +80,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false)
boolean inDevelopment = jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
cmUtils: cm,
changeManagement: [endpoint: 'https://example.org/cm'],
failIfStatusIsNotInDevelopment: false)
@ -92,7 +92,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(true, '0815')
jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
changeDocumentId: '42',
cmUtils: cm,
changeManagement: [type: 'SOLMAN',
@ -106,7 +106,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(true, '0815')
jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
cmUtils: cm,
changeManagement : [type: 'SOLMAN',
endpoint: 'https://example.org/cm'])
@ -133,7 +133,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
}
jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
cmUtils: cm,
changeManagement: [type: 'SOLMAN',
endpoint: 'https://example.org/cm'])
@ -149,7 +149,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false, null)
jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
cmUtils: cm,
changeManagement: [endpoint: 'https://example.org/cm',
type: 'SOLMAN'])
@ -165,7 +165,7 @@ class CheckChangeInDevelopmentTest extends BasePiperTest {
ChangeManagement cm = getChangeManagementUtils(false, '')
jsr.step.checkChangeInDevelopment(
script: nullScript,
script: nullScript,
cmUtils: cm,
changeManagement: [type: 'SOLMAN',
endpoint: 'https://example.org/cm'])

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,134 @@
import com.sap.piper.Utils
import com.sap.piper.ConfigurationHelper
import groovy.transform.Field
@Field String STEP_NAME = 'githubPublishRelease'
@Field Set GENERAL_CONFIG_KEYS = ['githubApiUrl', 'githubTokenCredentialsId', 'githubServerUrl']
@Field Set STEP_CONFIG_KEYS = [
'addClosedIssues',
'addDeltaToLastRelease',
'customFilterExtension',
'excludeLabels',
'githubApiUrl',
'githubTokenCredentialsId',
'githubOrg',
'githubRepo',
'githubServerUrl',
'releaseBodyHeader',
'version'
]
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
void call(Map parameters = [:]) {
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
def script = parameters.script ?: [commonPipelineEnvironment: commonPipelineEnvironment]
// load default & individual configuration
Map config = ConfigurationHelper.newInstance(this)
.loadStepDefaults()
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS)
.mixin(parameters, PARAMETER_KEYS)
.addIfEmpty('githubOrg', script.commonPipelineEnvironment.getGithubOrg())
.addIfEmpty('githubRepo', script.commonPipelineEnvironment.getGithubRepo())
.addIfEmpty('version', script.commonPipelineEnvironment.getArtifactVersion())
.withMandatoryProperty('githubOrg')
.withMandatoryProperty('githubRepo')
.withMandatoryProperty('githubTokenCredentialsId')
.withMandatoryProperty('version')
.use()
new Utils().pushToSWA([step: STEP_NAME], config)
withCredentials([string(credentialsId: config.githubTokenCredentialsId, variable: 'TOKEN')]) {
def releaseBody = config.releaseBodyHeader?"${config.releaseBodyHeader}<br />":''
def content = getLastRelease(config, TOKEN)
if (config.addClosedIssues)
releaseBody += addClosedIssue(config, TOKEN, content.published_at)
if (config.addDeltaToLastRelease)
releaseBody += addDeltaToLastRelease(config, content.tag_name)
postNewRelease(config, TOKEN, releaseBody)
}
}
}
Map getLastRelease(config, TOKEN){
def result = [:]
def response = httpRequest "${config.githubApiUrl}/repos/${config.githubOrg}/${config.githubRepo}/releases/latest?access_token=${TOKEN}"
if (response.status == 200) {
result = readJSON text: response.content
} else {
echo "[${STEP_NAME}] This is the first release - no previous releases available"
config.addDeltaToLastRelease = false
}
return result
}
String addClosedIssue(config, TOKEN, publishedAt){
if (config.customFilterExtension) {
config.customFilterExtension = "&${config.customFilterExtension}"
}
def publishedAtFilter = publishedAt ? "&since=${publishedAt}": ''
def response = httpRequest "${config.githubApiUrl}/repos/${config.githubOrg}/${config.githubRepo}/issues?access_token=${TOKEN}&per_page=100&state=closed&direction=asc${publishedAtFilter}${config.customFilterExtension}"
def result = ''
content = readJSON text: response.content
//list closed pull-requests
result += '<br />**List of closed pull-requests since last release**<br />'
for (def item : content) {
if (item.pull_request && !isExcluded(item, config.excludeLabels)) {
result += "[#${item.number}](${item.html_url}): ${item.title}<br />"
}
}
//list closed issues
result += '<br />**List of closed issues since last release**<br />'
for (def item : content) {
if (!item.pull_request && !isExcluded(item, config.excludeLabels)) {
result += "[#${item.number}](${item.html_url}): ${item.title}<br />"
}
}
return result
}
String addDeltaToLastRelease(config, latestTag){
def result = ''
//add delta link to previous release
result += '<br />**Changes**<br />'
result += "[${latestTag}...${config.version}](${config.githubServerUrl}/${config.githubOrg}/${config.githubRepo}/compare/${latestTag}...${config.version}) <br />"
return result
}
void postNewRelease(config, TOKEN, releaseBody){
releaseBody = releaseBody.replace('"', '\\"')
//write release information
def data = "{\"tag_name\": \"${config.version}\",\"target_commitish\": \"master\",\"name\": \"${config.version}\",\"body\": \"${releaseBody}\",\"draft\": false,\"prerelease\": false}"
try {
httpRequest httpMode: 'POST', requestBody: data, url: "${config.githubApiUrl}/repos/${config.githubOrg}/${config.githubRepo}/releases?access_token=${TOKEN}"
} catch (e) {
echo """[${STEP_NAME}] Error occured when writing release information
---------------------------------------------------------------------
Request body was:
---------------------------------------------------------------------
${data}
---------------------------------------------------------------------"""
throw e
}
}
boolean isExcluded(item, excludeLabels){
def result = false
excludeLabels.each {labelName ->
item.labels.each { label ->
if (label.name == labelName) {
result = true
}
}
}
return result
}