Repository: JetBrains/compose-multiplatform
File: tools/changelog/changelog.main.kts (Kotlin)

Code before:
fun checkPr() {
    val filePath = argsKeyless.getOrNull(0) ?: error("Please specify a file that contains PR description as the first argument")

    val body = File(filePath).readText()
    val releaseNotes = extractReleaseNotes(body, 0, "https://github.com/JetBrains/compose-multiplatform/pull/0")

    val nonstandardSections = releaseNotes?.entries
        .orEmpty()
        .filter { it.section !in standardSections || it.subsection !in standardSubsections }
        .map { "${it.section} - ${it.subsection}" }
        .toSet()

    println()

    when {
        releaseNotes is ReleaseNotes.Specified && releaseNotes.entries.isEmpty() -> {
            err.println("""
                "## Release Notes" doesn't contain any items, or section isn't specified
            
                See the format in $prFormatLink
            """.trimIndent())
            exitProcess(1)
        }
        releaseNotes is ReleaseNotes.Specified && nonstandardSections.isNotEmpty() -> {
            err.println("""
                "## Release Notes" contains nonstandard section - subsection pairs:
                ${nonstandardSections.joinToString(", ")}
            
                Allowed sections: ${standardSections.joinToString(", ")}
                Allowed subsections: ${standardSubsections.joinToString(", ")}
            
                See the full format in $prFormatLink
            """.trimIndent())
            exitProcess(1)
        }
        releaseNotes == null -> {
            err.println("""
                "## Release Notes" section is missing in the PR description
            
                See the format in $prFormatLink
            """.trimIndent())
            exitProcess(1)
        }
        else -> {
            println("\"## Release Notes\" are correct")
        }
    }
}

/**
 * September 2024

Review comment (suggestion):
I'd suggesting putting something around "section - subsection" (like single/double quotes), to clarify the structure of the sentence.

Code after:
fun checkPr() {
    val filePath = argsKeyless.getOrNull(0) ?: error("Please specify a file that contains PR description as the first argument")

    val body = File(filePath).readText()
    val releaseNotes = extractReleaseNotes(body, 0, "https://github.com/JetBrains/compose-multiplatform/pull/0")

    val nonstandardSections = releaseNotes?.entries
        .orEmpty()
        .filter { it.section !in standardSections || it.subsection !in standardSubsections }
        .map { "${it.section} - ${it.subsection}" }
        .toSet()

    println()

    when {
        releaseNotes is ReleaseNotes.Specified && releaseNotes.entries.isEmpty() -> {
            err.println("""
                "## Release Notes" doesn't contain any items, or "### Section - Subsection" isn't specified
            
                See the format in $prFormatLink
            """.trimIndent())
            exitProcess(1)
        }
        releaseNotes is ReleaseNotes.Specified && nonstandardSections.isNotEmpty() -> {
            err.println("""
                "## Release Notes" contains nonstandard "Section - Subsection" pairs:
                ${nonstandardSections.joinToString(", ")}
            
                Allowed sections: ${standardSections.joinToString(", ")}
                Allowed subsections: ${standardSubsections.joinToString(", ")}
            
                See the full format in $prFormatLink
            """.trimIndent())
            exitProcess(1)
        }
        releaseNotes == null -> {
            err.println("""
                "## Release Notes" section is missing in the PR description
            
                See the format in $prFormatLink
            """.trimIndent())
            exitProcess(1)
        }
        else -> {
            println("\"## Release Notes\" are correct")
        }
    }
}

/**
 * September 2024