diff --git a/.github/workflows/deploy-maven-central.yml b/.github/workflows/deploy-maven-central.yml new file mode 100644 index 0000000..b484fbe --- /dev/null +++ b/.github/workflows/deploy-maven-central.yml @@ -0,0 +1,89 @@ +name: Deploy to Maven Central + +on: + pull_request: + types: [opened, synchronize] + branches: [main] + +jobs: + deploy: + if: github.head_ref == 'develop' || startsWith(github.head_ref, 'release/') + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@v5 + with: + gpg_private_key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + + - name: Set up Java + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@v2 + + - name: Determine version from branch + id: version + run: | + BRANCH_NAME="${{ github.head_ref }}" + echo "Source branch: $BRANCH_NAME" + + # Set version based on branch name + if [[ "$BRANCH_NAME" =~ ^release/v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then + VERSION="${BASH_REMATCH[1]}" + echo "Release branch detected, version: $VERSION" + elif [[ "$BRANCH_NAME" == "main" ]]; then + VERSION="1.2.1" + echo "Main branch detected, using base version: $VERSION" + else + SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9]/-/g') + VERSION="1.2.1-${SANITIZED_BRANCH}-SNAPSHOT" + echo "Feature branch detected, version: $VERSION" + fi + + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Final version: $VERSION" + + - name: Debug environment variables + run: | + echo "Maven Username present: ${{ secrets.MAVEN_USERNAME != '' }}" + echo "Maven Password present: ${{ secrets.MAVEN_PASSWORD != '' }}" + echo "GPG Key present: ${{ secrets.MAVEN_GPG_PRIVATE_KEY != '' }}" + echo "GPG Passphrase present: ${{ secrets.MAVEN_GPG_PASSPHRASE != '' }}" + echo "Version: ${{ steps.version.outputs.version }}" + + - name: Publish package + run: > + ./gradlew + -PmavenCentralUsername=${{ secrets.MAVEN_USERNAME }} + -PmavenCentralPassword=${{ secrets.MAVEN_PASSWORD }} + -PsigningInMemoryKeyId=${{ secrets.MAVEN_GPG_KEY_ID }} + -PsigningInMemoryPassword=${{ secrets.MAVEN_GPG_PASSPHRASE }} + publishAndReleaseToMavenCentral + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + + - name: Auto-merge PR on successful deployment + if: success() + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GIT_TOKEN }} + script: | + const pr = context.payload.pull_request; + if (pr) { + await github.rest.pulls.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + merge_method: 'merge' + }); + console.log(`PR #${pr.number} has been automatically merged after successful deployment`); + } \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index fdf8d99..bb44937 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 9776158..fbf065b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,59 @@ +import com.vanniktech.maven.publish.SonatypeHost + plugins { - kotlin("jvm") version "1.9.0" + kotlin("jvm") version "2.1.0" application + `maven-publish` + signing + id("io.github.gradle-nexus.publish-plugin") version "1.3.0" + id("com.vanniktech.maven.publish") version "0.29.0" +} + +object Conf { + const val GROUP = "net.kigawa" + + // Base version - will be modified based on branch name if available + const val BASE_VERSION = "1.2.1" +} + +// Determine version based on branch name +// Branch naming convention for releases: release/vx.x.x (e.g., release/v1.0.0) +fun determineVersion(): String { + // Try to get branch name from different environment variables + // For pull requests, GITHUB_HEAD_REF contains the source branch name + // For direct pushes, GITHUB_REF_NAME contains the branch name + val branchName = System.getenv("GITHUB_HEAD_REF") + ?: System.getenv("GITHUB_REF_NAME") + ?: return Conf.BASE_VERSION + + // For main branch, use the base version + if (branchName == "main") { + return Conf.BASE_VERSION + } + + // For release branches in format 'release/vx.x.x', use the version from the branch name + val releasePattern = Regex("^release/v(\\d+\\.\\d+\\.\\d+)$") + val matchResult = releasePattern.find(branchName) + if (matchResult != null) { + // Extract version number from branch name + val versionFromBranch = matchResult.groupValues[1] + return versionFromBranch + } + + // For other branches, use format: baseVersion-branchName-SNAPSHOT + // Replace any non-alphanumeric characters with dashes for Maven compatibility + val sanitizedBranchName = branchName.replace(Regex("[^a-zA-Z0-9]"), "-") + return "${Conf.BASE_VERSION}-${sanitizedBranchName}-SNAPSHOT" } -group = "net.kigawa" -version = "1.0.0" +val projectVersion = determineVersion() +group = Conf.GROUP +version = projectVersion +allprojects { + group = Conf.GROUP + version = projectVersion +} repositories { mavenCentral() } @@ -21,3 +69,69 @@ tasks.test { kotlin { jvmToolchain(8) } + + +publishing { + // Configure all publications + publications.withType { + // disabled https://github.com/vanniktech/gradle-maven-publish-plugin/issues/754 + // and configured at library build.gradle.kts using `JavadocJar.Dokka("dokkaHtml")`. + /* + // Stub javadoc.jar artifact + artifact(tasks.register("${name}JavadocJar", Jar::class) { + archiveClassifier.set("javadoc") + archiveAppendix.set(this@withType.name) + })*/ + + // Provide artifacts information required by Maven Central + pom { + name = "renlin-router" + description = "routing library for renlin" + url = "https://github.com/Code-Sakura/renlin-router" + properties = mapOf( + ) + licenses { + license { + name.set("MIT License") + url.set("http://www.opensource.org/licenses/mit-license.php") + } + } + developers { + developer { + id.set("net.kigawa") + name.set("kigawa") + email.set("contact@kigawa.net") + } + developer { + id.set("io.github.seizavl") + name.set("seizavl") + email.set("") + } + } + scm { + connection.set("scm:git:https://github.com/Code-Sakura/renlin-router.git") + developerConnection.set("scm:git:https://github.com/Code-Sakura/renlin-router.git") + url.set("https://github.com/Code-Sakura/renlin-router") + } + } + } +} + +signing { + if (project.hasProperty("mavenCentralUsername") || + System.getenv("ORG_GRADLE_PROJECT_mavenCentralUsername") != null + ) { + useGpgCmd() + // It is not perfect (fails at some dependency assertions), better handled as + // `signAllPublications()` (as in vanniktech maven publish plugin) at build.gradle.kts. + //sign(publishing.publications) + } +} + +mavenPublishing { + publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) + if (project.hasProperty("mavenCentralUsername") || + System.getenv("ORG_GRADLE_PROJECT_mavenCentralUsername") != null + ) + signAllPublications() +} \ No newline at end of file diff --git a/gradle-plugin/build.gradle.kts b/gradle-plugin/build.gradle.kts index 053d86b..308d5c3 100644 --- a/gradle-plugin/build.gradle.kts +++ b/gradle-plugin/build.gradle.kts @@ -2,11 +2,17 @@ plugins { kotlin("jvm") `java-gradle-plugin` `maven-publish` + signing } group = "net.kigawa" version = "1.0.0" +repositories { + gradlePluginPortal() + mavenCentral() +} + gradlePlugin { plugins { create("renlinCompiler") { @@ -28,16 +34,66 @@ kotlin { jvmToolchain(8) } +java { + withSourcesJar() + withJavadocJar() +} + +// Version from environment or project property +version = project.findProperty("version") as String? ?: "1.0.0" + publishing { publications { register("mavenJava", MavenPublication::class) { from(components["kotlin"]) groupId = "net.kigawa" - artifactId = "net.kigawa.gradle.plugin" - version = "1.0.0" + artifactId = "renlin-compiler-gradle-plugin" + + pom { + name.set("Renlin Compiler Gradle Plugin") + description.set("Gradle plugin that enables automatic value injection for @AutoFill annotated parameters using Kotlin Compiler Plugin") + url.set("https://github.com/kigawa01/kcp-for-renlin") + + licenses { + license { + name.set("MIT License") + url.set("https://opensource.org/licenses/MIT") + } + } + + developers { + developer { + id.set("kigawa01") + name.set("kigawa") + email.set("kigawa.inbox@gmail.com") + } + } + + scm { + connection.set("scm:git:git://github.com/kigawa01/kcp-for-renlin.git") + developerConnection.set("scm:git:ssh://github.com:kigawa01/kcp-for-renlin.git") + url.set("https://github.com/kigawa01/kcp-for-renlin") + } + } } } repositories { mavenLocal() } +} + + +signing { + val signingKey: String? by project + val signingPassword: String? by project + val hasSigningCredentials = (System.getenv("GPG_SIGNING_KEY") != null && System.getenv("GPG_SIGNING_PASSWORD") != null) || + (signingKey != null && signingPassword != null) + + if (hasSigningCredentials) { + useInMemoryPgpKeys( + System.getenv("GPG_SIGNING_KEY") ?: signingKey, + System.getenv("GPG_SIGNING_PASSWORD") ?: signingPassword + ) + sign(publishing.publications) + } } \ No newline at end of file diff --git a/gradle-plugin/src/main/kotlin/net/kigawa/renlin/RenlinCompilerPlugin.kt b/gradle-plugin/src/main/kotlin/net/kigawa/renlin/RenlinCompilerPlugin.kt index 887ce52..38c6018 100644 --- a/gradle-plugin/src/main/kotlin/net/kigawa/renlin/RenlinCompilerPlugin.kt +++ b/gradle-plugin/src/main/kotlin/net/kigawa/renlin/RenlinCompilerPlugin.kt @@ -49,7 +49,7 @@ class RenlinCompilerPlugin : KotlinCompilerPluginSupportPlugin { override fun getPluginArtifact(): SubpluginArtifact { return SubpluginArtifact( groupId = "net.kigawa", - artifactId = "kotlin-plugin", + artifactId = "renlin-compiler-kotlin-plugin", version = "1.0.0", ) } diff --git a/kotlin-plugin/build.gradle.kts b/kotlin-plugin/build.gradle.kts index 2fb3229..f9075d7 100644 --- a/kotlin-plugin/build.gradle.kts +++ b/kotlin-plugin/build.gradle.kts @@ -1,11 +1,17 @@ plugins { kotlin("jvm") `maven-publish` + signing } group = "net.kigawa" version = "1.0.0" +repositories { + gradlePluginPortal() + mavenCentral() +} + dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0") implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.0") @@ -18,16 +24,66 @@ kotlin { jvmToolchain(8) } +java { + withSourcesJar() + withJavadocJar() +} + +// Version from environment or project property +version = project.findProperty("version") as String? ?: "1.0.0" + publishing { publications { register("mavenJava", MavenPublication::class) { from(components["kotlin"]) groupId = "net.kigawa" - artifactId = "kotlin-plugin" - version = "1.0.0" + artifactId = "renlin-compiler-kotlin-plugin" + + pom { + name.set("Renlin Compiler Kotlin Plugin") + description.set("Kotlin Compiler Plugin that automatically injects values for @AutoFill annotated parameters during compilation") + url.set("https://github.com/kigawa01/kcp-for-renlin") + + licenses { + license { + name.set("MIT License") + url.set("https://opensource.org/licenses/MIT") + } + } + + developers { + developer { + id.set("kigawa01") + name.set("kigawa") + email.set("kigawa.inbox@gmail.com") + } + } + + scm { + connection.set("scm:git:git://github.com/kigawa01/kcp-for-renlin.git") + developerConnection.set("scm:git:ssh://github.com:kigawa01/kcp-for-renlin.git") + url.set("https://github.com/kigawa01/kcp-for-renlin") + } + } } } repositories { mavenLocal() } +} + + +signing { + val signingKey: String? by project + val signingPassword: String? by project + val hasSigningCredentials = (System.getenv("GPG_SIGNING_KEY") != null && System.getenv("GPG_SIGNING_PASSWORD") != null) || + (signingKey != null && signingPassword != null) + + if (hasSigningCredentials) { + useInMemoryPgpKeys( + System.getenv("GPG_SIGNING_KEY") ?: signingKey, + System.getenv("GPG_SIGNING_PASSWORD") ?: signingPassword + ) + sign(publishing.publications) + } } \ No newline at end of file diff --git a/sample-project/build.gradle.kts b/sample-project/build.gradle.kts index b348625..2d20acc 100644 --- a/sample-project/build.gradle.kts +++ b/sample-project/build.gradle.kts @@ -25,7 +25,7 @@ repositories { dependencies { implementation(kotlin("stdlib")) - implementation("net.kigawa:kotlin-plugin:1.0.0") + implementation("net.kigawa:renlin-compiler-kotlin-plugin:1.0.0") testImplementation(kotlin("test")) } diff --git a/sample-project/src/main/kotlin/net/kigawa/sample/TestComponent.kt b/sample-project/src/main/kotlin/net/kigawa/sample/TestComponent.kt index 0b316ad..037f832 100644 --- a/sample-project/src/main/kotlin/net/kigawa/sample/TestComponent.kt +++ b/sample-project/src/main/kotlin/net/kigawa/sample/TestComponent.kt @@ -7,10 +7,7 @@ class TestComponent { fun render(@AutoFill key: String? = null, content: String) { println("TestComponent.render called with key: '$key', content: '$content'") } - - fun process(@AutoFill id: String?, @AutoFill name: String?, value: Int) { - println("TestComponent.process called with id: '$id', name: '$name', value: $value") - } + } // 通常の関数でもアノテーション付きパラメータを使用可能 diff --git a/settings.gradle.kts b/settings.gradle.kts index bf028e0..e738e2a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,6 @@ pluginManagement { repositories { + gradlePluginPortal() mavenCentral() } plugins {