-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32 from cloudogu/feature/30_release_process_funct…
…ions Add release process functions
- Loading branch information
Showing
11 changed files
with
946 additions
and
281 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,10 @@ Jenkins Pipeline Shared library, that contains additional features for Git, Mave | |
- [Branches](#branches) | ||
- [SonarCloud](#sonarcloud) | ||
- [Pull Requests in SonarQube](#pull-requests-in-sonarqube) | ||
- [Changelog](#changelog) | ||
- [changelogFileName](#changelogFileName) | ||
- [GitHub](#github) | ||
- [GitFlow](#gitflow) | ||
- [Steps](#steps) | ||
- [mailIfStatusChanged](#mailifstatuschanged) | ||
- [isPullRequest](#ispullrequest) | ||
|
@@ -476,38 +480,44 @@ gitWithCreds 'https://your.repo' // Implicitly passed credentials | |
|
||
### Changes to local repository | ||
|
||
Note that most changing operations offer parameters to specify an author. | ||
Theses parameters are optional. If not set the author of the last commit will be used as author and committer. | ||
You can specify a different committer by setting the following fields: | ||
|
||
* `git.committerName = 'the name'` | ||
* `git.committerEmail = '[email protected]` | ||
|
||
It is recommended to set a different committer, so it's obvious those commits were done by Jenkins in the name of | ||
the author. This behaviour is implemented by GitHub for example when committing via the Web UI. | ||
|
||
* `git.checkout('branchname')` | ||
* `git.checkoutOrCreate('branchname')` - Creates new Branch if it does not exist | ||
* `git.add('.')` | ||
* `git.commit('message', 'Author', '[email protected])` | ||
* `git.commit('message')` - uses the name and email of the last committer as author and committer. | ||
* `git.commit('message')` - uses default author/committer (see above). | ||
* `git.setTag('tag', 'message', 'Author', '[email protected])` | ||
* `git.setTag('tag', 'message')` - uses the name and email of the last committer as author and committer. | ||
* `git.setTag('tag', 'message')` - uses default author/committer (see above). | ||
* `git.fetch()` | ||
* `git.pull()` - pulls, and in case of merge, uses the name and email of the last committer as author and committer. | ||
* `git.pull()` - pulls, and in case of merge, uses default author/committer (see above). | ||
* `git.pull('refspec')` - pulls specific refspec (e.g. `origin master`), and in case of merge, uses the name and email | ||
of the last committer as author and committer. | ||
* `git.pull('refspec', 'Author', '[email protected])` | ||
* `git.merge('develop', 'Author', '[email protected])` | ||
* `git.merge('develop')` - uses the name and email of the last committer as author and committer. | ||
* `git.merge('develop')` - uses default author/committer (see above). | ||
* `git.mergeFastForwardOnly('master')` | ||
|
||
### Changes to remote repository | ||
|
||
* `git.push('master')` - pushes origin | ||
* `git.push('origin master')` - pushes origin | ||
**Note**: This always prepends `origin` if not present for historical reasonse (see #44). | ||
That is, right now it is impossible to push other remotes. | ||
This will change in the next major version of ces-build-lib. | ||
This limitation does not apply to other remote-related operations such as `pull()`, `fetch()` and `pushAndPullOnFailure()` | ||
So it's recommended to explicitly mention the origin and not just the refsepc: | ||
* Do: `git.push('origin master')` | ||
* Don't: `git.push('master')` because this will no longer work in the next major version. | ||
* `git.pushAndPullOnFailure('refspec')` - pushes and pulls if push failed e.g. because local and remote have diverged, | ||
then tries pushing again | ||
* `pushGitHubPagesBranch('folderToPush', 'commit Message')` - Commits and pushes a folder to the `gh-pages` branch of | ||
the current repo. Can be used to conveniently deliver websites. See https://pages.github.com. Note: | ||
* Uses the name and email of the last committer as author and committer. | ||
* the `gh-pages` branch is temporarily checked out to the `.gh-pages` folder. | ||
* Don't forget to create a git object with credentials. | ||
* Optional: You can deploy to a sub folder of your GitHub Pages branch using a third parameter | ||
* Examples: | ||
* [cloudogu/continuous-delivery-slides](https://github.com/cloudogu/continuous-delivery-slides/) | ||
* [cloudogu/k8s-security-3-things](https://github.com/cloudogu/k8s-security-3-things) | ||
* See also [Cloudogu Blog: Continuous Delivery with reveal.js](https://cloudogu.com/en/blog/continuous-delivery-with-revealjs) | ||
|
||
|
||
# Docker | ||
|
||
|
@@ -792,6 +802,94 @@ So a PR build is treated just like any other. That is, | |
The Jenkins GitHub Plugin sets `BRANCH_NAME` to the PR Name, e.g. `PR-42`. | ||
|
||
|
||
# Changelog | ||
Provides the functionality to read changes of a specific version in a changelog that is | ||
based on the changelog format on https://keepachangelog.com/. | ||
|
||
Note: The changelog will automatically be formatted. Characters like `"`, `'`, `\` will be removed. | ||
A `\n` will be replaced with `\\n`. This is done to make it possible to pass this string to a json | ||
struct as a value. | ||
|
||
Example: | ||
|
||
```groovy | ||
Changelog changelog = new Changelog(this) | ||
stage('Changelog') { | ||
String changes = changelog.getChangesForVersion('v1.0.0') | ||
// ... | ||
} | ||
``` | ||
## changelogFileName | ||
You can optionally pass the path to the changelog file if it is located somewhere else than in the root path or | ||
if the file name is not `CHANGELOG.md`. | ||
|
||
Example: | ||
|
||
```groovy | ||
Changelog changelog = new Changelog(this, 'myNewChangelog.md') | ||
stage('Changelog') { | ||
String changes = changelog.getChangesForVersion('v1.0.0') | ||
// ... | ||
} | ||
``` | ||
|
||
# GitHub | ||
Provides the functionality to do changes on a github repository such as creating a new release. | ||
|
||
Example: | ||
|
||
```groovy | ||
Git git = new Git(this) | ||
GitHub github = new GitHub(this, git) | ||
stage('Github') { | ||
github.createRelease('v1.1.1', 'Changes for version v1.1.1') | ||
} | ||
``` | ||
|
||
* `github.createRelease(releaseVersion, changes)` - Creates a release on github. | ||
* Use the `releaseVersion` (String) as name and tag. | ||
* Use the `changes` (String) as body of the release. | ||
* `github.createReleaseWithChangelog(releaseVersion, changelog)` - Creates a release on github. | ||
* Use the `releaseVersion` (String) as name and tag. | ||
* Use the `changelog` (Changelog) to extract the changes out of a changelog and add them to the body of the release. | ||
* `pushPagesBranch('folderToPush', 'commit Message')` - Commits and pushes a folder to the `gh-pages` branch of | ||
the current repo. Can be used to conveniently deliver websites. See https://pages.github.com. Note: | ||
* Uses the name and email of the last committer as author and committer. | ||
* the `gh-pages` branch is temporarily checked out to the `.gh-pages` folder. | ||
* Don't forget to create a git object with credentials. | ||
* Optional: You can deploy to a sub folder of your GitHub Pages branch using a third parameter | ||
* Examples: | ||
* [cloudogu/continuous-delivery-slides](https://github.com/cloudogu/continuous-delivery-slides/) | ||
* [cloudogu/k8s-security-3-things](https://github.com/cloudogu/k8s-security-3-things) | ||
* See also [Cloudogu Blog: Continuous Delivery with reveal.js](https://cloudogu.com/en/blog/continuous-delivery-with-revealjs) | ||
|
||
|
||
# GitFlow | ||
|
||
A wrapper class around the Git class to simplify the use of the git flow branching model. | ||
|
||
Example: | ||
|
||
```groovy | ||
Git git = new Git(this) | ||
git.committerName = 'jenkins' | ||
git.committerEmail = '[email protected]' | ||
GitFlow gitflow = new GitFlow(this, git) | ||
stage('Gitflow') { | ||
if (gitflow.isReleaseBranch()){ | ||
gitflow.finishRelease(git.getSimpleBranchName()) | ||
} | ||
} | ||
``` | ||
|
||
* `gitflow.isReleaseBranch()` - Checks if the currently checked out branch is a gitflow release branch. | ||
* `gitflow.finishRelease(releaseVersion)` - Finishes a git release by merging into develop and master. | ||
* Use the `releaseVersion` (String) as the name of the new git release. | ||
|
||
# Steps | ||
|
||
## mailIfStatusChanged | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package com.cloudogu.ces.cesbuildlib | ||
|
||
/** | ||
* Provides the functionality to read changes of a specific version in a changelog that is | ||
* based on the changelog format on https://keepachangelog.com/. | ||
*/ | ||
class Changelog implements Serializable { | ||
private script | ||
private String changelogFileName | ||
|
||
Changelog(script) { | ||
this(script, 'CHANGELOG.md') | ||
} | ||
|
||
Changelog(script, changelogFileName) { | ||
this.script = script | ||
this.changelogFileName = changelogFileName | ||
} | ||
|
||
/** | ||
* @return Returns the content of the given changelog. | ||
*/ | ||
private String readChangelog(){ | ||
script.readFile changelogFileName | ||
} | ||
|
||
/** | ||
* Extracts the changes for a given version out of the changelog. | ||
* | ||
* @param releaseVersion The version to get the changes for. | ||
* @return Returns the changes as String. | ||
*/ | ||
String changesForVersion(String releaseVersion) { | ||
def changelog = readChangelog() | ||
def start = changesStartIndex(changelog, releaseVersion) | ||
def end = changesEndIndex(changelog, start) | ||
return escapeForJson(changelog.substring(start, end).trim()) | ||
} | ||
|
||
/** | ||
* Removes characters from a string that could break the json struct when passing the string as json value. | ||
* | ||
* @param string The string to format. | ||
* @return Returns the formatted string. | ||
*/ | ||
private static String escapeForJson(String string) { | ||
return string | ||
.replace("\"", "") | ||
.replace("'", "") | ||
.replace("\\", "") | ||
.replace("\n", "\\n") | ||
} | ||
|
||
/** | ||
* Returns the start index of changes of a specific release version in the changelog. | ||
* | ||
* @param releaseVersion The version to get the changes for. | ||
* @return Returns the index in the changelog string where the changes start. | ||
*/ | ||
private static int changesStartIndex(String changelog, String releaseVersion) { | ||
def index = changelog.indexOf("## [${releaseVersion}]") | ||
if (index == -1){ | ||
throw new IllegalArgumentException("The desired version '${releaseVersion}' could not be found in the changelog.") | ||
} | ||
def offset = changelog.substring(index).indexOf("\n") | ||
return index + offset | ||
} | ||
|
||
/** | ||
* Returns the end index of changes of a specific release version in the changelog. | ||
* | ||
* @param start The start index of the changes for this version. | ||
* @return Returns the index in the changelog string where the changes end. | ||
*/ | ||
private static int changesEndIndex(String changelog, int start) { | ||
def changelogAfterStartIndex = changelog.substring(start) | ||
def index = changelogAfterStartIndex.indexOf("\n## [") | ||
if (index == -1) { | ||
return changelog.length() | ||
} | ||
return index + start | ||
} | ||
} |
Oops, something went wrong.