In Jenkins I'm building a step that reads CHANGELOG.md
and uses regex to extract the latest changelog from giving version.
The used .groovy
code:
#!/usr/bin/env groovy
import java.nio.file.Files
import java.nio.file.Paths
import java.util.regex.Pattern
def String currentTag = '0.1.0';
def String changelogFileName = 'CHANGELOG.md';
def changelogText = new String(Files.readAllBytes(Paths.get(changelogFileName)))
def pattern = Pattern.compile("(?s)^## ${currentTag}.*?(?=\n\n## |\\z)", Pattern.MULTILINE)
def matcher = pattern.matcher(changelogText)
if (matcher.find()) {
def latestChangelog = matcher.group()
println latestChangelog.strip()
}
The used input file:
# Changelog - Project
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
Changelog based on guidelines from
[Keep a CHANGELOG](http://keepachangelog.com/).
## 0.3.0 - 2022-06-30
### Changed:
- MDN-XXXX: blabla
### Also Changed:
- MDN-XXXX: blabla
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla
## 0.1.1 - 2022-06-08
### Fixed:
- MDN-XXXX: blabla
## 0.1.0 - 2022-06-08
### Added:
- MDN-XXXX: blabla
- MDN-XXXX: blabla
Locally this code works great. However, I want to use it in Jenkins, and there it's a security issues to directly import these:
import java.nio.file.Files
import java.nio.file.Paths
import java.util.regex.Pattern
Hence, I need to change it to Jenkins friendly code.
So I changed it to this:
def changelogText = readFile(file: changelogFileName)
def pattern = "(?s)^## ${currentTag}.*?(?=\n\n## |\\z)"
def matcher = (changelogText =~ pattern)
if (matcher.find()) {
def latestChangelog = matcher.group();
println(latestChangelog.strip());
} else {
println('Could not parse latest changelog.');
}
However, I keep getting 'Could not parse latest changelog.'
It's quite hard to debug when I have to run it on Jenkins the whole time.
Does anyone know how to make the Jenkins libraries available locally, or better, how I can match using Pattern.MULTILINE
?
Or perhaps a suggestion for a whole different approach?
To match all symbols including newlines, you can use [\s\S]
. This will work without any flags.
Consider the following demo:
String changelogText = """
# Changelog - Project
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
Changelog based on guidelines from
[Keep a CHANGELOG](http://keepachangelog.com/).
## 0.3.0 - 2022-06-30
### Changed:
- MDN-XXXX: blabla
### Also Changed:
- MDN-XXXX: blabla
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla
## 0.1.1 - 2022-06-08
### Fixed:
- MDN-XXXX: blabla
## 0.1.0 - 2022-06-08
### Added:
- MDN-XXXX: blabla
- MDN-XXXX: blabla
"""
def currentTag = "0.2.0 - 2022-06-09"
def pattern = /## ${currentTag}[\s\S]*?(?=\n\n## |\z)/
def matcher = (changelogText =~ pattern)
if (matcher.find()) {
def latestChangelog = matcher[0];
println(latestChangelog);
} else {
println('Could not parse latest changelog.');
}
Output:
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla