Publish KMM Library to Android Library on Maven Central with Sonatype Jira

이태훈·2022년 8월 17일

오늘은 KMM Library를 Sonatype Jira Maven Central로 Android Library를 배포하는 법을 알아보겠습니다.

크게 세 가지의 단계로 알아보겠습니다. 각 단계가 이미 적용되어 있으신 분들은 다음 단계를 보시면 됩니다.

  • Sonatype Jira 계정 생성
  • Issue ticker Repository 생성
  • gpg key 생성
  • Publish Repository
  • Release Repository

Sonatype Jira 계정 생성

먼저, 링크를 통해 Sonatype Jira 계정을 생성해줍니다.

Issue 생성

링크에서 이슈를 생성해줍니다.

Summary : 대충 아무 제목 적어주시면 됩니다.
Group Id : 그림1의 가이드와 같이 작성해주시면 됩니다.
Project URL : Library의 주소입니다. 임의의 레포지토리를 넣어주도록 하겠습니다.
SCM URL : Git repository의 경우 레포지토리 주소 끝에 .git 붙여주시면 됩니다.

1

Issue ticket Repository 생성

위의 화면에서 생성된 이슈 화면입니다. 다음 화면에서 티켓 번호를 확인할 수 있습니다.
필자의 번호는 OSSRH-83686인 것을 확인할 수 있습니다.

바로 깃허브로 가서 레포를 생성해줍니다. 레포 이름에 티켓 번호만 적어주면 됩니다.

조금 기다리다보면 아래와 같이 레포지토리가 준비됐다고 코멘트가 달립니다. 이제 배포 스크립트만 작성하면 됩니다.

gpg key 생성

artifact에 signing을 하기 위해 gpg key를 생성해줍니다.

맥 기준으로 gpg 설치는 brew install gnupg를 터미널에 입력하시면 됩니다.

설치가 완료되면 gpg --gen-key를 입력해 키를 생성해줍니다.

간단하게 이름, 이메일을 입력하고 Okay를 입력하고 passphrase(비밀번호)를 입력해줍니다.

여기서 저희는 keyId, secret key ring file, password 이 세 가지 정보를 사용할 겁니다.

keyId는 public key의 마지막 8자리를 사용합니다.
password는 passpharse를 사용합니다.
secret key ring file은 다음과 같이 생성해줍니다.

$ gpg --export-secret-keys -o secret.gpg

마지막으로 공개키를 서버에 전송해줍니다.

gpg --keyserver keyserver.ubuntu.com --send-keys keyId

Publishing

먼저 key id와 계정 정보등을 사용하기 위해 local.properties를 작성합니다.

signing.keyId= --> gpg key id <--
signing.password= --> gpg passphrase <--
signing.secretKeyRingFile= --> gpg secret ket ring file path <--

ossrhUsername= --> sonatype jira account user name <--
ossrhPassword= --> sonatype jira account password <--

android publish를 도와줄 gradle plugin을 만들어 줍니다.

루트 프로젝트에 convention-plugins 모듈을 만들어 줍니다.

convention-plugins 모듈의 그래이들을 작업해줍니다.

// convention/build.gradle.kts
plugins {
	`kotlin-dsl`
}

repositories {
	gradlePluginPortal()
}

다시 루트 프로젝트로가서 settings.gradle.kts에서

includeBuild("convention-plugins)

를 추가해줍니다.

android.publication.gradle.kts를 source 폴더 안에 넣어주고 publication 스크립트를 작성해줍니다.

plugins {
	`maven-publish`
	signing
}

ext["signing.keyId"] = null
ext["signing.password"] = null
ext["signing.secretKeyRingFile"] = null
ext["ossrhUsername"] = null
ext["ossrhPassword"] = null

val publishGroupId: String by project
val publishArtifactId: String by project
val pomName: String by project
val pomDescription: String by project
val siteUrl: String by project
val gitUrl: String by project
val licenseName: String by project
val licenseUrl: String by project
val developerId: String by project
val developerName: String by project
val developerEmail: String by project
val properties = rootProject.file("local.properties").reader().use {
	Properties().apply {
		load(it)
	}
}.onEach { (name, value) ->
	ext[name.toString()] = value
}

afterEvaluate {
	publishing {
		repositories {
			maven {
				name = "sonatype"
				setUrl("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
				credentials {
					username = properties["ossrhUsername"].toString()
					password = properties["ossrhPassword"].toString()
				}
			}
		}
		publications {
			register<MavenPublication>("release") {
				groupId = publishGroupId
				artifactId = publishArtifactId
				version = "1.0.0"
				from(components.getByName("release"))

				pom {
					name.set(pomName)
					description.set(pomDescription)
					url.set(siteUrl)

					licenses {
						license {
							name.set(licenseName)
							url.set(licenseUrl)
						}
					}
					developers {
						developer {
							id.set(developerId)
							name.set(developerName)
							email.set(developerEmail)
						}
					}
					scm {
						url.set(gitUrl)
					}
				}
			}
		}
	}
}

signing {
	sign(publishing.publications)
}

저는 gradle.properties에 다음과 publishGroupId, publishArtifactId, ..를 정의해줬습니다.

publishGroupId=io.github.taehoonleee
publishArtifactId=naver-login-kotlin-sdk
pomName=Sample Naver Login Library
pomDescription=Sample Naver Login Library target (iOS + Android)
siteUrl=https://github.com/TaehoonLeee/naver-login-kotliin-sdk
gitUrl=https://github.com/TaehoonLeee/naver-login-kotliin-sdk.git
licenseName=Apache License 2.0
licenseUrl=http://www.apache.org/licenses/LICENSE-2.0
developerId=leetaehoon
developerName=Taehoon Lee
developerEmail=lyc9290@gmail.com

그런 다음 kmm library의 gradle에서 작업하겠습니다.

plugins {
  id("android.publication")
}

먼저, 우리가 작성한 플러그인을 넣어줍니다.

android {
  compileSdk = 32
  sourceSets["main'].manifest.srcFile("src/androidMain/AndroidManifest.xml")
  defaultConfig {
    minSdk = 21
    targetSDk = 32
  }
  publishing {
    signleVariant("release") {
      withSourceJar()
      withJavadocJar()
    }
  }
}

그런 다음 안드로이드 타겟 라이브러리만 만들 것이기 때문에 android configuration에서 진행하겠습니다.

publishing {
  singleVariant("release") {
    withSourceJar()
    withJavadocJar()
  }
}

이 부분만 추가해주시면 됩니다.

경우에 따라 withJavadocJar()이나 withSourceJar()를 생략해주셔도 됩니다.

여러 varinats archive를 배포하시고 싶으신 분은

multipleVariants {
  allVariants() 또는 includeBuildTypeValues("debug", "release")
}

이렇게 사용하시면 됩니다.

이렇게 스크립트를 작성하신 다음

./gradlew publishReleasePublicationToSonatypeRepository

를 실행해주시면 배포과정이 진행됩니다.

Release

gradle build가 성공적으로 끝나면 링크에 들어가셔서 status가 open인 repository를 발견하실 수 있습니다.

해당 레포지토리를 클릭해서 하단 Content Tab에서 누락된 파일이 있는지 체크합니다. 그런 다음 Close 버튼을 누릅니다.

Close 버튼을 누르면 Repository를 검사하는데, Activity 탭을 통해 진행 상황을 볼 수 있습니다.

위의 그림처럼 Repository closed 스텝까지 도달하면 Release 버튼을 눌러 최종적으로 배포를 시작합니다. 이 release 과정은 시간이 걸릴 수 있습니다(몇십분 ~ 2시간).

만약, 첫 배포시면 release가 완료되면 아래와 같이 이슈에 코멘트가 달립니다.

레포지토리가 릴리즈되면 기존에 gradle에서 dependency 넣는 것 처럼 넣으시면 됩니다.

저의 경우에 kmm 프로젝트가 아닌 안드로이드 네이티브 플랫폼에서 사용할 일이 있어서 안드로이드 종속적인 라이브러리로 만들어봤습니다.

다음에는 안드로이드와 iOS에서 사용할 수 있는 라이브러리로 만들어보는 포스팅을 해보겠습니다.


References

https://developer.android.com/studio/publish-library/upload-library#create-pub
https://stackoverflow.com/a/63502756
https://dev.to/kotlin/how-to-build-and-publish-a-kotlin-multiplatform-library-going-public-4a8k
https://velog.io/@james-chun-dev/maven-배포-jcenter-에서-maven-으로-마이그레이션#gpg-키-인증
https://getstream.io/blog/publishing-libraries-to-mavencentral-2021/

profile
https://www.linkedin.com/in/%ED%83%9C%ED%9B%88-%EC%9D%B4-7b9563237

0개의 댓글