liferoad commented on code in PR #36021:
URL: https://github.com/apache/beam/pull/36021#discussion_r2316307086
##########
build.gradle.kts:
##########
@@ -510,6 +510,133 @@ tasks.register("pythonFormatterPreCommit") {
dependsOn("sdks:python:test-suites:tox:pycommon:formatter")
}
+tasks.register("formatChanges") {
+ group = "formatting"
+ description = "Formats CHANGES.md according to the template structure"
+
+ doLast {
+ val changesFile = file("CHANGES.md")
+ if (!changesFile.exists()) {
+ throw GradleException("CHANGES.md file not found")
+ }
+
+ val content = changesFile.readText()
+ val lines = content.lines().toMutableList()
+
+ // Find template end (after --> that follows <!-- Template -->)
+ var templateStartIndex = -1
+ var templateEndIndex = -1
+
+ for (i in lines.indices) {
+ if (lines[i].trim() == "<!-- Template -->") {
+ templateStartIndex = i
+ } else if (templateStartIndex != -1 && lines[i].trim() == "-->") {
+ templateEndIndex = i
+ break
+ }
+ }
+
+ if (templateEndIndex == -1) {
+ throw GradleException("Template end marker not found in CHANGES.md")
+ }
+
+ // Process each release section
+ var i = templateEndIndex + 1
+ val formattedLines = mutableListOf<String>()
+
+ // Keep header and template exactly as-is (lines 0 to templateEndIndex
inclusive)
+ formattedLines.addAll(lines.subList(0, templateEndIndex + 1))
+
+ // Always add blank line after template
+ formattedLines.add("")
+
+ while (i < lines.size) {
+ val line = lines[i]
+
+ // Check if this is a release header
+ if (line.startsWith("# [")) {
+ formattedLines.add(line)
+ i++
+
+ // Expected sections in order (following template)
+ val expectedSections = listOf(
+ "## Beam 3.0.0 Development Highlights",
+ "## Highlights",
+ "## I/Os",
+ "## New Features / Improvements",
+ "## Breaking Changes",
+ "## Deprecations",
+ "## Bugfixes",
+ "## Security Fixes",
+ "## Known Issues"
+ )
+
+ val sectionContent = mutableMapOf<String, MutableList<String>>()
+ var currentSection = ""
+
+ // Parse existing sections
+ while (i < lines.size && !lines[i].startsWith("# [")) {
+ val currentLine = lines[i]
+
+ if (currentLine.startsWith("## ")) {
+ currentSection = currentLine
+ if (!sectionContent.containsKey(currentSection)) {
+ sectionContent[currentSection] = mutableListOf()
+ }
+ } else if (currentSection.isNotEmpty()) {
+ sectionContent[currentSection]!!.add(currentLine)
+ }
+ i++
+ }
+
+ // Only add sections that actually exist with content
+ for (section in expectedSections) {
+ if (sectionContent.containsKey(section)) {
+ formattedLines.add("")
+ formattedLines.add(section)
+ formattedLines.add("")
+
+ // Remove empty lines at start and end
+ val content = sectionContent[section]!!
+ while (content.isNotEmpty() && content.first().trim().isEmpty()) {
+ content.removeAt(0)
+ }
+ while (content.isNotEmpty() && content.last().trim().isEmpty()) {
+ content.removeAt(content.size - 1)
+ }
+
+ // Format content according to template rules
+ val formattedContent = content.map { line ->
+ // Convert SDK language references from [Language] to (Language)
+
line.replace(Regex("\\[([^\\]]*(?:Java|Python|Go|Kotlin|TypeScript|YAML)[^\\]]*)\\]"))
{ matchResult ->
+ val languages = matchResult.groupValues[1]
+ // Only convert if it's clearly a language reference (not a
link or other content)
+ if
(languages.matches(Regex(".*(?:Java|Python|Go|Kotlin|TypeScript|YAML).*"))) {
+ "($languages)"
+ } else {
+ matchResult.value
+ }
+ }
+ }
+
+ formattedLines.addAll(formattedContent)
+ }
+ }
+
+ if (i < lines.size) {
+ formattedLines.add("")
+ }
+ } else {
+ i++
+ }
+ }
+
+ // Write formatted content back
+ changesFile.writeText(formattedLines.joinToString("\n"))
Review Comment:
Yes, that is the next item on my list.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]