జావా ప్రాజెక్ట్‌ను సోనాటైప్ మావెన్ సెంట్రల్ రిపోజిటరీకి ప్రచురించడానికి గ్రేడిల్ మరియు గితుబ్ చర్యలను ఉపయోగించడం

ఈ కథనంలో, గ్రేడిల్ బిల్డర్‌ని ఉపయోగించి సోనాటైప్ మావెన్ సెంట్రల్ రిపోజిటరీకి గితుబ్ చర్యల ద్వారా జావా కళాఖండాన్ని మొదటి నుండి ప్రచురించే ప్రక్రియను నేను వివరంగా పరిశీలించాలనుకుంటున్నాను.

ఒకే చోట సాధారణ ట్యుటోరియల్ లేకపోవడంతో ఈ వ్యాసం రాయాలని నిర్ణయించుకున్నాను. మొత్తం సమాచారాన్ని వివిధ మూలాల నుండి ఒక్కొక్కటిగా సేకరించవలసి ఉంటుంది, అంతేకాకుండా, పూర్తిగా తాజాది కాదు. ఎవరు పట్టించుకుంటారు, పిల్లి కింద స్వాగతం.

సోనాటైప్‌లో రిపోజిటరీని సృష్టిస్తోంది

సోనాటైప్ మావెన్ సెంట్రల్‌లో రిపోజిటరీని సృష్టించడం మొదటి దశ. దీని కోసం మేము వెళ్తాము ఇక్కడ, రిపోజిటరీని సృష్టించమని మమ్మల్ని అడుగుతూ, రిజిస్టర్ చేసి, కొత్త టాస్క్‌ని సృష్టించండి. మేము మాలో డ్రైవ్ చేస్తాము గ్రూప్ఐడి ప్రాజెక్ట్, ప్రాజెక్ట్ URL ప్రాజెక్ట్ లింక్ మరియు SCM url ప్రాజెక్ట్ ఉన్న సంస్కరణ నియంత్రణ వ్యవస్థకు లింక్. గ్రూప్ఐడి ఇక్కడ com.example, com.example.domain, com.example.testsupport రూపంలో ఉండాలి మరియు మీ గితుబ్‌కి లింక్ రూపంలో కూడా ఉండవచ్చు: github.com/yurusername -> io.github.yourusername. ఏదైనా సందర్భంలో, మీరు ఈ డొమైన్ లేదా ప్రొఫైల్ యాజమాన్యాన్ని ధృవీకరించాలి. మీరు గితుబ్ ప్రొఫైల్‌ను పేర్కొన్నట్లయితే, మీరు కోరుకున్న పేరుతో పబ్లిక్ రిపోజిటరీని సృష్టించమని అడగబడతారు.

నిర్ధారణ తర్వాత కొంత సమయం తర్వాత, మీ GroupId సృష్టించబడుతుంది మరియు మేము తదుపరి దశ, Gradle కాన్ఫిగరేషన్‌కు వెళ్లవచ్చు.

Gradleని కాన్ఫిగర్ చేస్తోంది

వ్రాసే సమయంలో, కళాఖండాన్ని ప్రచురించడంలో సహాయపడే గ్రాడిల్ ప్లగిన్‌లు నాకు కనిపించలేదు. నేను కనుగొన్న ఏకైక ప్లగ్ఇన్, అయితే, రచయిత దానికి మరింత మద్దతు ఇవ్వడానికి నిరాకరించారు. అందువల్ల, దీన్ని చేయడం చాలా కష్టం కాదు కాబట్టి, నేను ప్రతిదీ నేనే చేయాలని నిర్ణయించుకున్నాను.

పబ్లిషింగ్ కోసం Sonatype యొక్క అవసరాలు గుర్తించడానికి మొదటి విషయం. అవి క్రిందివి:

  • సోర్స్ కోడ్‌లు మరియు 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
            }
        }
    }
}

ఇది sonatype వినియోగదారు పేరు и sonatypePassword నమోదు సమయంలో సృష్టించబడిన లాగిన్ మరియు పాస్‌వర్డ్‌ను కలిగి ఉన్న వేరియబుల్స్ sonatype.org.

ఆ విధంగా ఫైనల్ build.gradle ఇలా కనిపిస్తుంది:

పూర్తి 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@dev.ru'
                }
            }
        }
    }
}

పర్యావరణ వేరియబుల్ నుండి మేము సంస్కరణను పొందుతామని నేను గమనించాలనుకుంటున్నాను: System.getenv('RELEASE_VERSION'). మేము దానిని అసెంబ్లీ సమయంలో బహిర్గతం చేస్తాము మరియు ట్యాగ్ పేరు నుండి తీసుకుంటాము.

PGP కీ ఉత్పత్తి

అన్ని ఫైల్‌లు GPG/PGP కీతో సంతకం చేయడం Sonatype యొక్క అవసరాలలో ఒకటి. దీని కోసం మేము వెళ్తాము ఇక్కడ మరియు మీ ఆపరేటింగ్ సిస్టమ్ కోసం GnuPG యుటిలిటీని డౌన్‌లోడ్ చేయండి.

  • మేము ఒక కీ జతని రూపొందిస్తాము: gpg --gen-key, వినియోగదారు పేరు, ఇ-మెయిల్ నమోదు చేయండి మరియు పాస్‌వర్డ్‌ను కూడా సెట్ చేయండి.
  • మేము కనుగొంటాము id ఆదేశంతో మా కీ: gpg --list-secret-keys --keyid-format short. స్లాష్ తర్వాత Id పేర్కొనబడుతుంది, ఉదాహరణకు: 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 చర్యలను సెటప్ చేస్తోంది

చివరి దశకు వెళ్దాం, గితుబ్ చర్యలను ఉపయోగించి బిల్డ్‌ని సెటప్ చేయండి మరియు ఆటో-పబ్లిష్ చేయండి.
Github చర్యలు అనేది పూర్తి CI / CD సైకిల్‌ని అమలు చేయడం ద్వారా వర్క్‌ఫ్లోను ఆటోమేట్ చేయడానికి మిమ్మల్ని అనుమతించే లక్షణం. బిల్డ్, టెస్ట్ మరియు డిప్లాయ్ వివిధ ఈవెంట్‌ల ద్వారా ప్రేరేపించబడవచ్చు: కోడ్ పుష్, విడుదల సృష్టి లేదా సమస్యలు. పబ్లిక్ రిపోజిటరీలకు ఈ కార్యాచరణ పూర్తిగా ఉచితం.

ఈ విభాగంలో, బిల్డ్ మరియు పుష్ కోడ్‌ను ఎలా సెటప్ చేయాలో మరియు విడుదలైనప్పుడు సోనాటైప్ రిపోజిటరీకి ఎలా అమర్చాలో, అలాగే రహస్యాలను సెటప్ చేయడం ఎలాగో నేను మీకు చూపుతాను.

మేము రహస్యాలను సెట్ చేసాము

ఆటోమేటిక్ అసెంబ్లీ మరియు విస్తరణ కోసం, కీ ఐడి, కీని రూపొందించేటప్పుడు మనం నమోదు చేసిన పాస్‌వర్డ్, PGP కీ మరియు సోనాటైప్ లాగిన్/పాస్‌వర్డ్ వంటి అనేక రహస్య విలువలు మనకు అవసరం. మీరు వాటిని రిపోజిటరీ సెట్టింగ్‌లలో ప్రత్యేక విభాగంలో సెట్ చేయవచ్చు:

జావా ప్రాజెక్ట్‌ను సోనాటైప్ మావెన్ సెంట్రల్ రిపోజిటరీకి ప్రచురించడానికి గ్రేడిల్ మరియు గితుబ్ చర్యలను ఉపయోగించడం

మేము ఈ క్రింది వేరియబుల్స్ సెట్ చేసాము:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - సోనాటైప్‌తో నమోదు చేసేటప్పుడు మేము నమోదు చేసిన లాగిన్ / పాస్‌వర్డ్
  • SIGNING_KEYID/SIGNING_PASSWORD — ఉత్పత్తి సమయంలో PGP కీ id మరియు పాస్‌వర్డ్ సెట్ చేయబడింది.

నేను 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 అక్షరాలను కత్తిరించాము. తరువాత, మేము ప్రచురణ కోసం ప్రామాణిక Gradle ఆదేశాలను ఉపయోగిస్తాము: test publish

సోనాటైప్ రిపోజిటరీలో విస్తరణ ఫలితాలను తనిఖీ చేస్తోంది

విడుదల సృష్టించబడిన తర్వాత, మునుపటి విభాగంలో వివరించిన వర్క్‌ఫ్లో ప్రారంభం కావాలి. దీన్ని చేయడానికి, విడుదలను సృష్టించండి:

జావా ప్రాజెక్ట్‌ను సోనాటైప్ మావెన్ సెంట్రల్ రిపోజిటరీకి ప్రచురించడానికి గ్రేడిల్ మరియు గితుబ్ చర్యలను ఉపయోగించడం

ట్యాగ్ పేరు తప్పనిసరిగా vతో ప్రారంభం కావాలి. విడుదలను ప్రచురించు క్లిక్ చేసిన తర్వాత, వర్క్‌ఫ్లో విజయవంతంగా పూర్తయితే, మనం దీనికి వెళ్లవచ్చు సోనాటైప్ నెక్సస్ నిర్ధారించుకోవడానికి:

జావా ప్రాజెక్ట్‌ను సోనాటైప్ మావెన్ సెంట్రల్ రిపోజిటరీకి ప్రచురించడానికి గ్రేడిల్ మరియు గితుబ్ చర్యలను ఉపయోగించడం

కళాకృతి స్టేజింగ్ రిపోజిటరీలో కనిపించింది. ఇది వెంటనే ఓపెన్ స్టేటస్‌లో కనిపిస్తుంది, ఆపై తగిన బటన్‌ను నొక్కడం ద్వారా దాన్ని క్లోజ్ స్టేటస్‌కి మాన్యువల్‌గా బదిలీ చేయాలి. అన్ని అవసరాలు తీర్చబడ్డాయో లేదో తనిఖీ చేసిన తర్వాత, ఆర్టిఫ్యాక్ట్ క్లోజ్ స్టేటస్‌లోకి వెళ్లి, ఇకపై సవరణకు అందుబాటులో ఉండదు. ఈ రూపంలో, ఇది మావెన్‌సెంట్రల్‌లో ముగుస్తుంది. అన్నీ సరిగ్గా ఉంటే, మీరు బటన్‌ను నొక్కవచ్చు విడుదల, మరియు కళాఖండం సోనాటైప్ రిపోజిటరీలో ముగుస్తుంది.

కళాకృతి మావెన్‌సెంట్రల్‌లోకి రావాలంటే, మేము ప్రారంభంలోనే సృష్టించిన పనిలో మీరు దానిని అడగాలి. మీరు దీన్ని ఒక్కసారి మాత్రమే చేయాలి, కాబట్టి మేము మొదటిసారిగా ప్రచురిస్తాము. తదుపరి సమయాల్లో, ఇది అవసరం లేదు, ప్రతిదీ స్వయంచాలకంగా సమకాలీకరించబడుతుంది. వారు నా కోసం సింక్రొనైజేషన్‌ని త్వరగా ఆన్ చేసారు, అయితే కళాకృతి MavenCentralలో అందుబాటులోకి రావడానికి సుమారు 5 రోజులు పట్టింది.

అంతే, మేము మా కళాఖండాన్ని మావెన్‌సెంట్రల్‌లో ప్రచురించాము.

ఉపయోగకరమైన లింకులు

  • ఇలాంటి వ్యాసం, మావెన్ ద్వారా మాత్రమే ప్రచురించండి
  • స్టేజింగ్ రిపోజిటరీ సోనాటైప్
  • Jira టాస్క్‌ని సృష్టించే సోనాటైప్
  • ఉదాహరణకు ఇది అన్ని సెటప్ చేయబడిన రిపోజిటరీ

మూలం: www.habr.com

DDoS రక్షణ, VPS VDS సర్వర్‌లతో సైట్‌ల కోసం నమ్మకమైన హోస్టింగ్‌ను కొనుగోలు చేయండి 🔥 DDoS రక్షణతో కూడిన నమ్మకమైన వెబ్‌సైట్ హోస్టింగ్, VPS VDS సర్వర్‌లను కొనండి | ProHoster