diff --git a/repoman/src/main/kotlin/org/metaborg/repoman/meta/RepoMetadata.kt b/repoman/src/main/kotlin/org/metaborg/repoman/meta/RepoMetadata.kt index 7efa883..77cd15f 100644 --- a/repoman/src/main/kotlin/org/metaborg/repoman/meta/RepoMetadata.kt +++ b/repoman/src/main/kotlin/org/metaborg/repoman/meta/RepoMetadata.kt @@ -2,6 +2,7 @@ package org.metaborg.repoman.meta import kotlinx.serialization.Serializable import org.metaborg.repoman.Markdown +import java.time.Year /** Default values. */ object Defaults { @@ -34,7 +35,7 @@ data class RepoMetadata( /** The inception year of the repository (required). */ val inceptionYear: String, /** The current year in which the repository is still maintained. */ - val currentYear: String = "2024", + val currentYear: String = Year.now().toString(), /** A list of Maven libraries published by the repo. */ val libraries: List = emptyList(), @@ -199,6 +200,18 @@ data class GithubIssueTemplates( val assignDevelopers: Boolean = true, /** Whether to use the GitHub Discussions tab. */ val useDiscussions: Boolean = true, + /** The type label to apply to bugs; or `null` to not apply a label. */ + val bugTypeLabel: String? = "bug", + /** The type label to apply to feature requests; or `null` to not apply a label. */ + val featureRequestTypeLabel: String? = "feature-request", + /** The type label to apply to questions; or `null` to not apply a label. */ + val questionTypeLabel: String? = "question", + /** The state label to apply to new bugs; or `null` to not apply a label. */ + val bugStateLabel: String? = "needs-triage", + /** The state label to apply to new feature requests; or `null` to not apply a label. */ + val featureRequestStateLabel: String? = null, + /** The state label to apply to new questions; or `null` to not apply a label. */ + val questionStateLabel: String? = null, ) /** A Maven artifact. */ diff --git a/repoman/src/main/resources/templates/github/ISSUE_TEMPLATE/20-report-a-bug.yml.kte b/repoman/src/main/resources/templates/github/ISSUE_TEMPLATE/20-report-a-bug.yml.kte index 7ac510c..ba4220f 100644 --- a/repoman/src/main/resources/templates/github/ISSUE_TEMPLATE/20-report-a-bug.yml.kte +++ b/repoman/src/main/resources/templates/github/ISSUE_TEMPLATE/20-report-a-bug.yml.kte @@ -10,7 +10,13 @@ name: "🐞 Report a Bug" description: File a bug report or issue for any project in ${meta.title}. title: "[Bug]: " -labels: ["bug", "triage"] +labels: + @if(meta.files.githubIssueTemplates.bugTypeLabel != null) + - "${meta.files.githubIssueTemplates.bugTypeLabel}" + @endif + @if(meta.files.githubIssueTemplates.bugStateLabel != null) + - "${meta.files.githubIssueTemplates.bugStateLabel}" + @endif @if(meta.files.githubIssueTemplates.assignDevelopers) assignees: @for(person in meta.developers) diff --git a/repoman/src/test/kotlin/org/metaborg/repoman/GenerateCommandTests.kt b/repoman/src/test/kotlin/org/metaborg/repoman/GenerateCommandTests.kt new file mode 100644 index 0000000..9cfe6c5 --- /dev/null +++ b/repoman/src/test/kotlin/org/metaborg/repoman/GenerateCommandTests.kt @@ -0,0 +1,169 @@ +package org.metaborg.repoman + +import com.github.ajalt.clikt.testing.test +import io.kotest.assertions.assertSoftly +import io.kotest.assertions.withClue +import io.kotest.core.spec.style.FunSpec +import io.kotest.engine.spec.tempdir +import io.kotest.matchers.file.shouldNotBeEmpty +import io.kotest.matchers.shouldBe + +/** Tests the [GenerateCommand]. */ +class GenerateCommandTests: FunSpec({ + + test("should generate the necessary files") { + // Arrange + val projectDir = tempdir() + val metadataFile = projectDir.resolve("repo.yaml") + // Try to exercise all the features + metadataFile.writeText( + """ + --- + repoOwner: "metaborgcube" + repoName: "queen" + mainBranch: "master" + releaseTagPrefix: "v" + mavenGroup: "org.metaborgcube" + + title: "Metaborgcube Queen" + description: "Resistance is futile." + documentationLink: "https://metaborgcube.dev/queen/" + inceptionYear: "2000" + currentYear: "2373" + + libraries: + - group: "org.metaborgcube" + name: "picard" + description: "Make it so." + - group: "org.metaborgcube" + name: "riker" + description: "Engage." + + languages: + - group: "org.metaborgcube" + name: "worf" + description: "Today is a good day to die." + - group: "org.metaborgcube" + name: "data" + description: "I am fully functional." + + plugins: + - id: "org.metaborgcube.enterprise" + description: "NCC-1701-D" + - id: "org.metaborgcube.voyager" + description: "NCC-74656" + + developers: + - id: "picard" + name: "Jean-Luc Picard" + email: "jl@enterprise.uss" + - id: "riker" + name: "William Riker" + email: "numberone@enterprise.uss" + + contributors: + - id: "worf" + name: "Worf" + email: "moghson@enterprise.uss" + - id: "data" + name: "Data" + email: "404@enterprise.uss" + + files: + readme: + generate: true + update: true + body: | + I am the beginning, the end, the one who is many. I am the Borg. + license: + generate: true + update: true + contributing: + generate: true + update: true + codeOfConduct: + generate: true + update: true + changelog: + generate: true + update: true + gitignore: + generate: true + update: true + extra: | + .dna/ + gradleWrapper: + generate: true + update: true + gradleVersion: "latest" + gradleDistributionType: "all" + gradleRootProject: + generate: true + update: true + rootProjectName: "queen" + includedBuilds: + - name: "sevenofnine" + path: "people/sevenofnine/" + includedProjects: + - name: ":core" + path: "core/" + - name: ":ui" + path: "ui/" + conventionVersion: "0.16.0" + createPublishTasks: true + githubWorkflows: + generate: true + update: true + publishRelease: true + publishSnapshot: true + buildTask: ":core:build" + publishTask: ":core:publish" + printVersionTask: ":core:printVersion" + buildDocs: true + githubIssueTemplates: + generate: true + update: true + assignDevelopers: true + useDiscussions: true + bugTypeLabel: "Type-Bug" + featureRequestTypeLabel: "Type-Enhancement" + questionTypeLabel: "Type-Question" + bugStateLabel: "State-Triage" + featureRequestStateLabel: "State-Triage" + questionStateLabel: "State-Triage" + """.trimIndent() + ) + + // Act + val result = CLI.test(arrayOf( + "generate", + "--meta", metadataFile.toString(), + "--repo", projectDir.toString(), + "--force-update" + )) + + // Assert + withClue(result.output) { + result.statusCode shouldBe 0 + } + assertSoftly { + projectDir.resolve("README.md").shouldNotBeEmpty() + projectDir.resolve("LICENSE.md").shouldNotBeEmpty() + projectDir.resolve("CONTRIBUTING.md").shouldNotBeEmpty() + projectDir.resolve("CODE_OF_CONDUCT.md").shouldNotBeEmpty() + projectDir.resolve("CHANGELOG.md").shouldNotBeEmpty() + projectDir.resolve(".gitignore").shouldNotBeEmpty() + projectDir.resolve("gradlew").shouldNotBeEmpty() + projectDir.resolve("gradlew.bat").shouldNotBeEmpty() + projectDir.resolve("gradle/wrapper/gradle-wrapper.jar").shouldNotBeEmpty() + projectDir.resolve("gradle/wrapper/gradle-wrapper.properties").shouldNotBeEmpty() + projectDir.resolve("settings.gradle.kts").shouldNotBeEmpty() + projectDir.resolve("build.gradle.kts").shouldNotBeEmpty() + projectDir.resolve(".github/workflows/build.yaml").shouldNotBeEmpty() + projectDir.resolve(".github/workflows/documentation.yaml").shouldNotBeEmpty() + projectDir.resolve(".github/ISSUE_TEMPLATE/config.yml").shouldNotBeEmpty() + projectDir.resolve(".github/ISSUE_TEMPLATE/20-report-a-bug.yml").shouldNotBeEmpty() + } + } + +}) \ No newline at end of file