рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдЧреНрд░реИрдбрд▓ рдмрд┐рд▓реНрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬреАрдердм рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдорд╛рд╡реЗрди рд╕реЗрдВрдЯреНрд░рд▓ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рдЬрд╛рд╡рд╛ рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдПрдХ рдЬрдЧрд╣ рд╕рд╛рдорд╛рдиреНрдп рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреА рдХрдореА рдХреЗ рдХрд╛рд░рдг рдореИрдВрдиреЗ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рд╕рднреА рд╕реВрдЪрдирд╛рдУрдВ рдХреЛ рд╡рд┐рднрд┐рдиреНрди рд╕реНрд░реЛрддреЛрдВ рд╕реЗ рдЯреБрдХрдбрд╝реЗ-рдЯреБрдХрдбрд╝реЗ рдХрд░рдХреЗ рдПрдХрддреНрд░ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдерд╛, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддрд╛рдЬрд╝рд╛ рдирд╣реАрдВред рдХреМрди рдкрд░рд╡рд╛рд╣ рдХрд░рддрд╛ рд╣реИ, рдмрд┐рд▓реНрд▓реА рдХреЗ рдиреАрдЪреЗ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдореЗрдВ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдмрдирд╛рдирд╛
рдкрд╣рд▓рд╛ рдХрджрдо рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдорд╛рд╡реЗрди рд╕реЗрдВрдЯреНрд░рд▓ рдореЗрдВ рдПрдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдмрдирд╛рдирд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдЬрд╛рддреЗ рд╣реИрдВ
рдкреБрд╖реНрдЯрд┐ рдХреЗ рдХреБрдЫ рд╕рдордп рдмрд╛рдж, рдЖрдкрдХреА GroupId рдмрди рдЬрд╛рдПрдЧреА рдФрд░ рд╣рдо рдЕрдЧрд▓реЗ рдЪрд░рдг, Gradle рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкрд░ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЧреНрд░реЗрдбрд▓ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛
рд▓реЗрдЦрди рдХреЗ рд╕рдордп, рдореБрдЭреЗ рдЧреНрд░реИрдбрд▓ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдирд╣реАрдВ рдорд┐рд▓реЗ рдЬреЛ рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХреЗред
рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рд╡рд╛рд▓реА рдкрд╣рд▓реА рдмрд╛рдд рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдХреА рдкреНрд░рдХрд╛рд╢рди рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рд╣реИрдВред рд╡реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИрдВ:
- рд╕реЛрд░реНрд╕ рдХреЛрдб рдФрд░ JavaDoc рдХреА рдЙрдкрд▓рдмреНрдзрддрд╛, рдпрд╛рдиреАред рд╣рд╛рдЬрд┐рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП
-sources.jar
╨╕-javadoc.jar
рдлрд╝рд╛рдЗрд▓реЗрдВред рдЬреИрд╕рд╛ рдХрд┐ рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИ, рдпрджрд┐ рд╕реНрд░реЛрдд рдХреЛрдб рдпрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдк рдПрдХ рдбрдореА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ-sources.jar
рдпрд╛-javadoc.jar
рдкрд░реАрдХреНрд╖рд╛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдВрджрд░ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд░реАрдбрдореЗ рдХреЗ рд╕рд╛рдеред - рд╕рднреА рдлрд╛рдЗрд▓реЛрдВ рдкрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП
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 protected]'
}
}
}
}
}
рдЕрдЧрд▓рд╛, рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдЙрддреНрдкрдиреНрди рд╣реЛрдиреЗ рдХреЗ рджреМрд░рд╛рди -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
}
}
}
}
рдпрд╣рд╛рдВ рд╕реЛрдирд╛рдЯрд╛рдЗрдкрдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдирд╛рдо ╨╕ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдкрд╛рд╕рд╡рд░реНрдб рдкрдВрдЬреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рдмрдирд╛рдП рдЧрдП рд▓реЙрдЧрд┐рди рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рд╡рд╛рд▓реЗ рдЪрд░
рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдлрд╛рдЗрдирд▓ build.gradle
рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:
рдкреВрд░реНрдг рдмрд┐рд▓реНрдб.рдЧреНрд░реЗрдбрд▓ рдХреЛрдб
plugins {
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 protected]'
}
}
}
}
}
рдореИрдВ рдпрд╣ рдиреЛрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдореЗрдВ рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рд╕реЗ рд╕рдВрд╕реНрдХрд░рдг рдорд┐рд▓рддрд╛ рд╣реИ: System.getenv('RELEASE_VERSION')
. рд╣рдо рдЗрд╕реЗ рдЕрд╕реЗрдВрдмрд▓реА рдХреЗ рджреМрд░рд╛рди рдПрдХреНрд╕рдкреЛрдЬрд╝ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рдЯреИрдЧ рдирд╛рдо рд╕реЗ рд▓реЗрдВрдЧреЗред
рдкреАрдЬреАрдкреА рдХреБрдВрдЬреА рдкреАрдврд╝реА
рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рд╣реИ рдХрд┐ рд╕рднреА рдлрд╛рдЗрд▓реЛрдВ рдкрд░ рдЬреАрдкреАрдЬреА/рдкреАрдЬреАрдкреА рдХреБрдВрдЬреА рдХреЗ рд╕рд╛рде рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд┐рдП рдЬрд╛рдПрдВред рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдЬрд╛рддреЗ рд╣реИрдВ
- рд╣рдо рдПрдХ рдкреНрд░рдореБрдЦ рдЬреЛрдбрд╝реА рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ:
gpg --gen-key
, рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо, рдИ-рдореЗрд▓ рджрд░реНрдЬ рдХрд░реЗрдВ, рдФрд░ рдПрдХ рдкрд╛рд╕рд╡рд░реНрдб рднреА рд╕реЗрдЯ рдХрд░реЗрдВред - рдкрддрд╛ рд▓рдЧрд╛рдирд╛
id
рдЖрджреЗрд╢ рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░реА рдХреБрдВрдЬреА:gpg --list-secret-keys --keyid-format short
. рд╕реНрд▓реИрд╢ рдХреЗ рдмрд╛рдж рдЖрдИрдбреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреА рдЬрд╛рдПрдЧреА, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП: rsa2048/9B695056 - рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдВрдЬреА рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдирд╛
https://keys.openpgp.org рдЖрджреЗрд╢ рджреНрд╡рд╛рд░рд╛:gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
- рд╣рдо рдЧреБрдкреНрдд рдХреБрдВрдЬреА рдХреЛ рдПрдХ рдордирдорд╛рдиреЗ рд╕реНрдерд╛рди рдкрд░ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ, рд╣рдореЗрдВ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:
gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
рдЧреАрдереВрдм рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рд╕реНрдерд╛рдкрдирд╛
рдЪрд▓рд┐рдП рдЕрдВрддрд┐рдо рдЪрд░рдг рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ, рдЬреАрдердм рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрд┐рд▓реНрдб рдФрд░ рдСрдЯреЛ-рдкрдмреНрд▓рд┐рд╢ рд╕реЗрдЯ рдЕрдк рдХрд░реЗрдВред
Github рдХреНрд░рд┐рдпрд╛рдПрдБ рдПрдХ рдРрд╕реА рд╕реБрд╡рд┐рдзрд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдкреВрд░реНрдг CI / CD рдЪрдХреНрд░ рд▓рд╛рдЧреВ рдХрд░рдХреЗ рд╡рд░реНрдХрдлрд╝реНрд▓реЛ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рдирд┐рд░реНрдорд╛рдг, рдкрд░реАрдХреНрд╖рдг рдФрд░ рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдХреЛ рд╡рд┐рднрд┐рдиреНрди рдШрдЯрдирд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдЯреНрд░рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рдХреЛрдб рдкреБрд╢, рд░рд┐рд▓реАрдЬрд╝ рдирд┐рд░реНрдорд╛рдг, рдпрд╛ рд╕рдорд╕реНрдпрд╛рдПрдБред рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдХреБрд▓ рдореБрдлреНрдд рд╣реИред
рдЗрд╕ рдЦрдВрдб рдореЗрдВ, рдореИрдВ рдЖрдкрдХреЛ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдмрд┐рд▓реНрдб рдФрд░ рдкреБрд╢ рдХреЛрдб рдХреИрд╕реЗ рд╕реЗрдЯ рдЕрдк рдХрд░реЗрдВ рдФрд░ рд░рд┐рд▓реАрдЬрд╝ рд╣реЛрдиреЗ рдкрд░ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рддреИрдирд╛рдд рдХрд░реЗрдВ, рд╕рд╛рде рд╣реА рд╕реАрдХреНрд░реЗрдЯреНрд╕ рднреА рд╕реЗрдЯ рдЕрдк рдХрд░реЗрдВред
рд╣рдо рд░рд╛рдЬрд╝ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ
рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЕрд╕реЗрдВрдмрд▓реА рдФрд░ рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдХрдИ рдЧреБрдкреНрдд рдорд╛рдиреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬреИрд╕реЗ рдХреБрдВрдЬреА рдЖрдИрдбреА, рд╡рд╣ рдкрд╛рд╕рд╡рд░реНрдб рдЬреЛ рд╣рдордиреЗ рдХреБрдВрдЬреА рдмрдирд╛рддреЗ рд╕рдордп рджрд░реНрдЬ рдХрд┐рдпрд╛ рдерд╛, рд╕реНрд╡рдпрдВ PGP рдХреБрдВрдЬреА, рдФрд░ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рд▓реЙрдЧрд┐рди/рдкрд╛рд╕рд╡рд░реНрдбред рдЖрдк рдЙрдиреНрд╣реЗрдВ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдЦрдВрдб рдореЗрдВ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ:
- SONATYPE_USERNAME / SONATYPE_PASSWORD - рд▓реЙрдЧрд┐рди / рдкрд╛рд╕рд╡рд░реНрдб рдЬрд┐рд╕реЗ рд╣рдордиреЗ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдХреЗ рд╕рд╛рде рдкрдВрдЬреАрдХрд░рдг рдХрд░рддреЗ рд╕рдордп рджрд░реНрдЬ рдХрд┐рдпрд╛ рдерд╛
- SIGNING_KEYID/SIGNING_PASSWORD тАФ рдЬрдирд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди PGP рдХреБрдВрдЬреА рдЖрдИрдбреА рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рд╕реЗрдЯред
рдореИрдВ GPG_KEY_CONTENTS рдЪрд░ рдкрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдзреНрдпрд╛рди рдХреЗрдиреНрджреНрд░рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд╢рди рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдПрдХ рдирд┐рдЬреА PGP рдХреБрдВрдЬреА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕реЗ рд╕реАрдХреНрд░реЗрдЯреНрд╕ рдореЗрдВ рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛
- рдЖрдЗрдП рд╣рдорд╛рд░реА рдХреБрдВрдЬреА рдХреЛ GPG рдХреЗ рд╕рд╛рде рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдХрд░реЗрдВ:
gpg --symmetric --cipher-algo AES256 9B695056.gpg
рдПрдХ рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░рдХреЗред рдЗрд╕реЗ рдПрдХ рдЪрд░ рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП: SECRET_PASSPHRASE - рдЖрдЗрдП рдмреЗрд╕ 64 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдПрдиреНрдХреНрд░рд┐рдкреНрдЯреЗрдб рдХреБрдВрдЬреА рдХреЛ рдЯреЗрдХреНрд╕реНрдЯ рдлреЙрд░реНрдо рдореЗрдВ рдЕрдиреБрд╡рд╛рджрд┐рдд рдХрд░реЗрдВ:
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
, рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдмрдирд╛рддреЗ рд╕рдордп рднреАред
рдХрд╛рд░реНрдп рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдИрд╡реЗрдВрдЯ рдкрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЪрд░рдг рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо ubuntu рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдкрд░ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВрдЧреЗ, рдЬрд╛рд╡рд╛ 8 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЧреНрд░реИрдбрд▓ рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧрдЗрди рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ eskatos/gradle-command-action@v1
рдЬреЛ рдмрд┐рд▓реНрдбрд░ рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрдорд╛рдВрдб рдЪрд▓рд╛рдПрдЧрд╛ arguments
. рдЪрд░ secrets.SONATYPE_USERNAME
╨╕ secrets.SONATYPE_PASSWORD
рдпреЗ рд╡реЗ рд░рд╣рд╕реНрдп рд╣реИрдВ рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рдкреВрдЫреЗ рдереЗред
рдмрд┐рд▓реНрдб рдкрд░рд┐рдгрд╛рдо рдХреНрд░рд┐рдпрд╛рдПрдБ рдЯреИрдм рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдВрдЧреЗ:
рдирдИ рд░рд┐рд▓реАрдЬ рдЬрд╛рд░реА рд╣реЛрдиреЗ рдкрд░ рдСрдЯреЛ-рддреИрдирд╛рддреА
рдЪрд▓рд┐рдП рд╕реНрд╡рддрдГ рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдХрд╛рд░реНрдпрдкреНрд░рд╡рд╛рд╣ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ 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 рд╡рд░реНрдгреЛрдВ рдХреЛ рдХрд╛рдЯ рджрд┐рдпрд╛ред рдЕрдЧрд▓рд╛, рд╣рдо рдкреНрд░рдХрд╛рд╢рди рдХреЗ рд▓рд┐рдП рдорд╛рдирдХ рдЧреНрд░реЗрдбрд▓ рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ: test publish
рд╕реЛрдирд╛рдЯрд╛рдЗрдк рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХрд░рдирд╛
рдПрдХ рдмрд╛рд░ рд░рд┐рд▓реАрдЬрд╝ рдмрди рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд╛рд░реНрдпрдкреНрд░рд╡рд╛рд╣ рдкреНрд░рд╛рд░рдВрдн рд╣реЛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рд░рд┐рд▓реАрдЬрд╝ рдмрдирд╛рдПрдБ:
рдЯреИрдЧ рдХрд╛ рдирд╛рдо v рд╕реЗ рд╢реБрд░реВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐, рдкреНрд░рдХрд╛рд╢рди рдкреНрд░рдХрд╛рд╢рди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдХрд╛рд░реНрдпрдкреНрд░рд╡рд╛рд╣ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреВрд░реНрдг рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ
рдЖрд░реНрдЯрд┐рдлреИрдХреНрдЯ рд╕реНрдЯреЗрдЬрд┐рдВрдЧ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ред рдпрд╣ рддреБрд░рдВрдд рдЦреБрд▓реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ, рдлрд┐рд░ рдЗрд╕реЗ рдЙрдЪрд┐рдд рдмрдЯрди рджрдмрд╛рдХрд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдмрдВрдж рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЬрд╛рдБрдЪрдиреЗ рдХреЗ рдмрд╛рдж рдХрд┐ рд╕рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдБ рдкреВрд░реА рд╣реЛ рдЧрдИ рд╣реИрдВ, рд╡рд┐рд░реВрдкрдг рд╕рд╛рдХреНрд╖реНрдп рдмрдВрдж рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЪрд▓рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЕрдм рд╕рдВрд╢реЛрдзрди рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИред рдЗрд╕ рд░реВрдк рдореЗрдВ, рдпрд╣ рдорд╛рд╡реЗрдирд╕реЗрдВрдЯреНрд░рд▓ рдореЗрдВ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдЕрдЧрд░ рд╕рдм рдареАрдХ рд╣реИ, рддреЛ рдЖрдк рдмрдЯрди рджрдмрд╛ рд╕рдХрддреЗ рд╣реИрдВ рд░рд┐рд▓реАрдЬ, рдФрд░ рдЖрд░реНрдЯрд┐рдлреИрдХреНрдЯ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
MavenCentral рдореЗрдВ рд╡рд┐рд░реВрдкрдг рд╕рд╛рдХреНрд╖реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЗрд╕реЗ рдЙрд╕ рдХрд╛рд░реНрдп рдореЗрдВ рдкреВрдЫрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдордиреЗ рд╢реБрд░реБрдЖрдд рдореЗрдВ рдмрдирд╛рдпрд╛ рдерд╛ред рдЖрдкрдХреЛ рдЗрд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдкрд╣рд▓реА рдмрд╛рд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдмрд╛рдж рдХреЗ рд╕рдордп рдореЗрдВ, рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рд╕рдм рдХреБрдЫ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдЙрдиреНрд╣реЛрдВрдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдЬрд▓реНрджреА рд╕реЗ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдЪрд╛рд▓реВ рдХрд░ рджрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рдорд╛рд╡реЗрдирд╕реЗрдВрдЯреНрд░рд▓ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реЛрдиреЗ рдореЗрдВ рд▓рдЧрднрдЧ 5 рджрд┐рди рд▓рдЧ рдЧрдПред
рдмрд╕ рдЗрддрдирд╛ рд╣реА, рд╣рдордиреЗ рдорд╛рд╡реЗрдирд╕реЗрдВрдЯреНрд░рд▓ рдореЗрдВ рдЕрдкрдиреА рдХрд▓рд╛рдХреГрддрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд┐рдпрд╛ рд╣реИред
рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХреНрд╕
- рдРрд╕рд╛ рд╣реА рдПрдХ
рд▓реЗрдЦ , рдХреЗрд╡рд▓ рдореЗрд╡реЗрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░реЗрдВ - рдордЪрд╛рди
рдХреЛрд╖ рд╕реЛрдирд╛рдЯрд╛рдЗрдк Jira рд╕реЛрдирд╛рдЯрд╛рдЗрдк рдЬрд┐рд╕рдореЗрдВ рдХрд╛рд░реНрдп рдмрдирд╛рдирд╛ рд╣реИрдЙрджрд╛рд╣рд░рдг рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдЬрд╣рд╛рдВ рдпрд╣ рд╕рдм рд╕реЗрдЯ рдЕрдк рд╣реИ
рд╕реНрд░реЛрдд: www.habr.com