рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдЧреНрд░реИрдб рдХрд▓реЗрдХреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдорд╛рд╡реЗрди рд╕реЗрдВрдЯреНрд░рд▓ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдЬреАрдердм рдПрдХреНрдЯреЗрд╢рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рдЬрд╛рд╡рд╛ рдЖрд░реНрдЯрд╡рд░реНрдХ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд░ рдПрдХ рд╡рд┐рд╕реНрддреГрдд рдирдЬрд╝рд░ рдбрд╛рд▓рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдореИрдВрдиреЗ рдПрдХ рдЬрдЧрд╣ рд╕рд╛рдорд╛рдиреНрдп рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреА рдХрдореА рдХреЗ рдХрд╛рд░рдг рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА рд╡рд┐рднрд┐рдиреНрди рд╕реНрд░реЛрддреЛрдВ рд╕реЗ рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рдПрдХрддреНрд░ рдХреА рдЬрд╛рдиреА рдереА, рдЬрдмрдХрд┐ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддрд╛рдЬрд╛ рдирд╣реАрдВ рдереАред рдХреМрди рдкрд░рд╡рд╛рд╣ рдХрд░рддрд╛ рд╣реИ, рдмрд┐рд▓реНрд▓реА рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдореЗрдВ рдПрдХ рднрдВрдбрд╛рд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдг
рдкрд╣рд▓рд╛ рдХрджрдо рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдорд╛рд╡реЗрди рд╕реЗрдВрдЯреНрд░рд▓ рдореЗрдВ рдПрдХ рднрдВрдбрд╛рд░ рдмрдирд╛рдирд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдВ рдЬрд╛рдПрдВ , рдкрдВрдЬреАрдХрд░рдг рдХрд░реЗрдВ рдФрд░ рдПрдХ рдирдпрд╛ рдХрд╛рд░реНрдп рдмрдирд╛рдПрдВ, рдЬрд┐рд╕рд╕реЗ рд╣рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ рдЬрд╛ рд╕рдХреЗред рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд╣рдорд╛рд░реЗ GroupId , Project URL рдХреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдФрд░ SCM url рд▓рд┐рдВрдХ рдХреЛ рдЙрд╕ рд╕рдВрд╕реНрдХрд░рдг рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рдЪрд▓рд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд┐рд╣рд┐рдд рд╣реИред рдпрд╣рд╛рдВ GroupId рдХреЙрдо рдХрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред com.example, com.example.domain, com.example.testsupport, рдФрд░ рдпрд╣ рдЖрдкрдХреЗ github: github.com/yourusername -> jio.github.yourusername рдХрд╛ рд▓рд┐рдВрдХ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ ред рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЖрдкрдХреЛ рдЗрд╕ рдбреЛрдореЗрди рдпрд╛ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХреЗ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рдиреА рд╣реЛрдЧреАред рдпрджрд┐ рдЖрдкрдиреЗ рдПрдХ рдЬреАрдереВрдм рдкреНрд░реЛрдлрд╛рдЗрд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рд╡реЗ рдЖрдкрдХреЛ рд╡рд╛рдВрдЫрд┐рдд рдирд╛рдо рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рднрдВрдбрд╛рд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВрдЧреЗред
рдкреБрд╖реНрдЯрд┐ рдХреЗ рдХреБрдЫ рд╕рдордп рдмрд╛рдж, рдЖрдкрдХрд╛ GroupId рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рд╣рдо рдЕрдЧрд▓реЗ рдЪрд░рдг, рдЧреНрд░реИрдбрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред
рдЧреНрд░реЗрдбрд┐рдВрдЧ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛
рдЗрд╕ рд▓реЗрдЦрди рдХреЗ рд╕рдордп, рдореБрдЭреЗ рдЧреНрд░реИрдбрд▓ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдирд╣реАрдВ рдорд┐рд▓рд╛ рдЬреЛ рдЖрд░реНрдЯрд╡рд░реНрдХ рдХреЗ рдкреНрд░рдХрд╛рд╢рди рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХреЗред рдпрд╣ рдПрдХрдорд╛рддреНрд░ рдкреНрд▓рдЧрдЗрди рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд▓реЗрдЦрдХ рдиреЗ рдЕрдкрдиреЗ рдЖрдЧреЗ рдХреЗ рд╕рдорд░реНрдерди рд╕реЗ рдЗрдирдХрд╛рд░ рдХрд░ рджрд┐рдпрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рдЦреБрдж рд╣реА рд╕рдм рдХреБрдЫ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХрд░рдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред
рдкрд╣рд▓реА рдмрд╛рдд рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рд╣реИ рдХрд┐ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдХреА рдкреНрд░рдХрд╛рд╢рди рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рд╣реИрдВред рд╡реЗ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ:
- рд╕реНрд░реЛрдд рдХреЛрдб рдФрд░ JavaDoc рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐, рдЕрд░реНрдерд╛рдд рдореМрдЬреВрдж рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП
-sources.jar
рдФрд░ -javadoc.jar
рдлрд╝рд╛рдЗрд▓реЗрдВред рдЬреИрд╕рд╛ рдХрд┐ рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИ, рдпрджрд┐ рд╕реНрд░реЛрдд рдХреЛрдб рдпрд╛ рдкреНрд░рд▓реЗрдЦрди рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдк рдкрд░реАрдХреНрд╖рдг рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдбрдореА -sources.jar
рдпрд╛ -javadoc.jar
рдПрдХ рд╕рд╛рдзрд╛рд░рдг README рдХреЗ тАЛтАЛрд╕рд╛рде рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ ред GPG/PGP
, .asc
, , .pom
groupId
, artifactId
version
. -SNAPSHOT
name
, description
url
- ,
, . .
build.gradle
. , , , url, . :
def customizePom(pom) {
pom.withXml {
def root = asNode()
root.dependencies.removeAll { dep ->
dep.scope == "test"
}
root.children().last() + {
resolveStrategy = DELEGATE_FIRST
description 'Some description of artifact'
name 'Artifct name'
url 'https://github.com/login/projectname'
organization {
name 'com.github.login'
url 'https://github.com/login'
}
issueManagement {
system 'GitHub'
url 'https://github.com/login/projectname/issues'
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
scm {
url 'https://github.com/login/projectname'
connection 'scm:https://github.com/login/projectname.git'
developerConnection 'scm:git://github.com/login/projectname.git'
}
developers {
developer {
id 'dev'
name 'DevName'
email 'email@dev.ru'
}
}
}
}
}
, -sources.jar
-javadoc.jar
. java
:
java {
withJavadocJar()
withSourcesJar()
}
, GPG/PGP . signing
:
plugins {
id 'signing'
}
:
signing {
sign publishing.publications
}
, publishing
:
publishing {
publications {
mavenJava(MavenPublication) {
customizePom(pom)
groupId group
artifactId archivesBaseName
version version
from components.java
}
}
repositories {
maven {
url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
credentials {
username sonatypeUsername
password sonatypePassword
}
}
}
}
sonatypeUsername sonatypePassword , , sonatype.org.
, build.gradle
:
build.gradleplugins {
id 'java'
id 'maven-publish'
id 'signing'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
withJavadocJar()
withSourcesJar()
}
group 'io.github.githublogin'
archivesBaseName = 'projectname'
version = System.getenv('RELEASE_VERSION') ?: "0.0.1"
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
}
test {
useJUnitPlatform()
}
jar {
from sourceSets.main.output
from sourceSets.main.allJava
}
signing {
sign publishing.publications
}
publishing {
publications {
mavenJava(MavenPublication) {
customizePom(pom)
groupId group
artifactId archivesBaseName
version version
from components.java
}
}
repositories {
maven {
url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
credentials {
username sonatypeUsername
password sonatypePassword
}
}
}
}
def customizePom(pom) {
pom.withXml {
def root = asNode()
root.dependencies.removeAll { dep ->
dep.scope == "test"
}
root.children().last() + {
resolveStrategy = DELEGATE_FIRST
description 'Some description of artifact'
name 'Artifct name'
url 'https://github.com/login/projectname'
organization {
name 'com.github.login'
url 'https://github.com/githublogin'
}
issueManagement {
system 'GitHub'
url 'https://github.com/githublogin/projectname/issues'
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
scm {
url 'https://github.com/githublogin/projectname'
connection 'scm:https://github.com/githublogin/projectname.git'
developerConnection 'scm:git://github.com/githublogin/projectname.git'
}
developers {
developer {
id 'dev'
name 'DevName'
email 'email@dev.ru'
}
}
}
}
}
, : System.getenv('RELEASE_VERSION')
. .
PGP
Sonatype GPG/PGP . GnuPG .
- :
gpg --gen-key
, , e-mail, . id
: gpg --list-secret-keys --keyid-format short
. Id , : rsa2048/9B695056- https://keys.openpgp.org :
gpg --keyserver https://keys.openpgp.org/ --send-keys 9B695056
- , :
gpg --export-secret-key 9B695056 > D:\\gpg\\9B695056.gpg
Github Actions
, , Github Actions.
Github Actions тАУ , , CI/CD. , : , issues. .
Sonatype , .
, id , , , PGP , / Sonatype. :

:
- SONATYPE_USERNAME/SONATYPE_PASSWORD тАФ /, Sonatype
- SIGNING_KEYID/SIGNING_PASSWORD тАФ id PGP , .
GPG_KEY_CONTENTS . , PGP . , , .
- gpg:
gpg --symmetric --cipher-algo AES256 9B695056.gpg
, . : SECRET_PASSPHRASE - base64:
base64 9B695056.gpg.gpg > 9B695056.txt
. : GPG_KEY_CONTENTS.
PR
: .github/workflows
.
, , gradle-ci-build.yml
:
name: build
on:
push:
branches:
- master
- dev
- testing
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Build with Gradle
uses: eskatos/gradle-command-action@v1
with:
gradle-version: current
arguments: build -PsonatypeUsername=${{secrets.SONATYPE_USERNAME}} -PsonatypePassword=${{secrets.SONATYPE_PASSWORD}}
master
, dev
testing
, .
jobs , . ubuntu, Java 8, Gradle eskatos/gradle-command-action@v1
, , arguments
. secrets.SONATYPE_USERNAME
secrets.SONATYPE_PASSWORD
, .
Actions:

gradle-ci-publish.yml
:
name: publish
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Prepare to publish
run: |
echo '${{secrets.GPG_KEY_CONTENTS}}' | base64 -d > publish_key.gpg
gpg --quiet --batch --yes --decrypt --passphrase="${{secrets.SECRET_PASSPHRASE}}" \
--output secret.gpg publish_key.gpg
echo "::set-env name=RELEASE_VERSION::${GITHUB_REF:11}"
- name: Publish with Gradle
uses: eskatos/gradle-command-action@v1
with:
gradle-version: current
arguments: test publish -Psigning.secretKeyRingFile=secret.gpg -Psigning.keyId=${{secrets.SIGNING_KEYID}} -Psigning.password=${{secrets.SIGNING_PASSWORD}} -PsonatypeUsername=${{secrets.SONATYPE_USERNAME}} -PsonatypePassword=${{secrets.SONATYPE_PASSWORD}}
, . , v.
PGP , . RELEASE_VERSION
gradle.build
. Prepare to publish
. GPG_KEY_CONTENTS, gpg , , secret.gpg
.
GITHUB_REF
, , . refs/tags/v0.0.2
11 , . Gradle : test publish
Sonatype
, . :

v. Publish release, , Sonatype Nexus :

Staging . Open, Close, . , Close . MavenCentral. , Release, Sonatype.
, MavenCentral, , . , . , . , MavenCentral 5 .
рдмрд╕ рдЗрддрдирд╛ рд╣реА, рд╣рдордиреЗ рдЕрдкрдиреА рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рдорд╛рд╡рдирд╕реЗрдиреНрдЯреНрд░рд▓ рдореЗрдВ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд┐рдпрд╛ред
рдЙрдкрдпреЛрдЧреА рдХрдбрд╝рд┐рдпрд╛рдБ
- рдЗрд╕реА рддрд░рд╣ рдХрд╛ рд▓реЗрдЦ , рдХреЗрд╡рд▓ рдорд╛рд╡реЗрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рдХрд╛рд╢рди
- рд╕реНрдЯреЗрдЬрд┐рдВрдЧ рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рд╕реЛрдирд╛рдЯрд╛рдЗрдк
- рдЬреАрд░рд╛ рд╕реЛрдирд╛рдЯрд╛рдЗрдк, рдЬрд┐рд╕рдореЗрдВ рдЖрдкрдХреЛ рдПрдХ рдХрд╛рд░реНрдп рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
- рдПрдХ рдЙрджрд╛рд╣рд░рдг рднрдВрдбрд╛рд░ рдЬрд╣рд╛рдВ рдпрд╣ рд╕рдм рд╕реНрдерд╛рдкрд┐рдд рд╣реИ