שימוש בפעולות Gradle ו-Github לפרסום Java Project במאגר המרכזי של Sonatype Maven

במאמר זה, אני רוצה להעיף מבט מפורט על תהליך פרסום חפץ Java מאפס דרך Github Actions למאגר Sonatype Maven Central באמצעות בונה Gradle.

החלטתי לכתוב את המאמר הזה בגלל היעדר הדרכה רגילה במקום אחד. כל המידע היה צריך להיאסף חלק אחר חלק ממקורות שונים, יתר על כן, לא לגמרי טרי. למי אכפת, ברוך הבא מתחת לחתול.

יצירת מאגר ב-Sonatype

הצעד הראשון הוא יצירת מאגר ב-Sonatype Maven Central. בשביל זה אנחנו הולכים כאן, הירשם וצור משימה חדשה, ומבקש מאיתנו ליצור מאגר. אנחנו נוסעים בתוך שלנו חבורה פּרוֹיֶקט, כתובת פרויקט קישור לפרויקט ו כתובת אתר SCM קישור למערכת בקרת הגרסאות בה נמצא הפרויקט. חבורה כאן צריך להיות בצורת com.example, com.example.domain, com.example.testsupport, ויכול להיות גם בצורה של קישור ל-github שלך: github.com/yourusername -> io.github.yourusername. בכל מקרה, תצטרך לאמת את הבעלות על הדומיין או הפרופיל הזה. אם ציינת פרופיל github, תתבקש ליצור מאגר ציבורי עם השם הרצוי.

זמן מה לאחר האישור, ה-GroupId שלך ייווצר ונוכל לעבור לשלב הבא, תצורת Gradle.

הגדרת 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 קוֹבֶץ. ראשית, בואו נוסיף את כל המידע הדרוש על המפתחים, הרישיונות, מערכת בקרת הגרסאות, וגם נקבע את כתובת האתר, השם והתיאור של הפרויקט. בוא נכתוב שיטה פשוטה לכך:

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

אחת הדרישות של Sonatype היא שכל הקבצים יהיו חתומים עם מפתח GPG/PGP. בשביל זה אנחנו הולכים כאן והורד את תוכנית השירות GnuPG עבור מערכת ההפעלה שלך.

  • אנו יוצרים זוג מפתחות: 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

בואו נעבור לשלב הסופי, נגדיר את הבנייה ופרסום אוטומטי באמצעות Github Actions.
Github Actions היא תכונה המאפשרת לך להפוך את זרימת העבודה לאוטומטית על ידי הטמעת מחזור CI/CD מלא. בנייה, בדיקה ופריסה יכולה להיות מופעלת על ידי אירועים שונים: דחיפה של קוד, יצירת שחרור או בעיות. פונקציונליות זו חינמית לחלוטין עבור מאגרים ציבוריים.

בסעיף זה, אני אראה לך כיצד להגדיר קוד לבנות ולדחוף ולפרוס למאגר Sonatype בשחרור, כמו גם להגדיר סודות.

אנחנו מגדירים סודות

להרכבה ופריסה אוטומטית, אנו זקוקים למספר ערכים סודיים, כגון מזהה המפתח, הסיסמה שהזנו בעת יצירת המפתח, מפתח ה-PGP עצמו וסיסמת הכניסה/סיסמה של Sonatype. אתה יכול להגדיר אותם בקטע מיוחד בהגדרות המאגר:

שימוש בפעולות Gradle ו-Github לפרסום Java Project במאגר המרכזי של Sonatype Maven

אנו מגדירים את המשתנים הבאים:

  • SONATYPE_USERNAME / SONATYPE_PASSWORD - כניסה / סיסמה שהזנו בעת ההרשמה ל-Sonatype
  • SIGNING_KEYID/SIGNING_PASSWORD — מזהה מפתח 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.

בניית הגדרות בעת דחיפת קוד ויצירת יחסי ציבור

ראשית עליך ליצור תיקיה בשורש הפרויקט שלך: .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, להשתמש ב-Java 8, וגם להשתמש בתוסף Gradle eskatos/gradle-command-action@v1אשר, באמצעות הגרסה העדכנית ביותר של ה-Builder, יפעיל את הפקודות שצוינו ב arguments. משתנים secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD אלו הסודות ששאלנו קודם.

תוצאות הבנייה יבואו לידי ביטוי בכרטיסייה פעולות:

שימוש בפעולות Gradle ו-Github לפרסום Java Project במאגר המרכזי של Sonatype Maven

פריסה אוטומטית כשיוצאת מהדורה חדשה

בואו ניצור קובץ זרימת עבודה נפרד לפריסה אוטומטית 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

לאחר יצירת המהדורה, זרימת העבודה שתוארה בסעיף הקודם אמורה להתחיל. כדי לעשות זאת, צור גרסה:

שימוש בפעולות Gradle ו-Github לפרסום Java Project במאגר המרכזי של Sonatype Maven

שם התג חייב להתחיל ב-v. אם, לאחר לחיצה על פרסם שחרור, זרימת העבודה הושלמה בהצלחה, נוכל לעבור אל סונטאפ נקסוס לוודא:

שימוש בפעולות Gradle ו-Github לפרסום Java Project במאגר המרכזי של Sonatype Maven

החפץ הופיע במאגר Staging. זה מופיע מיד בסטטוס פתיחה, ואז יש להעביר אותו ידנית למצב סגור על ידי לחיצה על הכפתור המתאים. לאחר בדיקה שכל הדרישות מתקיימות, החפץ עובר למצב סגור ואינו זמין עוד לשינוי. בצורה זו, זה יגיע ל-MavenCentral. אם הכל בסדר, אתה יכול ללחוץ על הכפתור לשחרר, והחפץ יסתיים במאגר Sonatype.

כדי שהחפץ ייכנס ל-MavenCentral, אתה צריך לבקש אותו במשימה שיצרנו ממש בהתחלה. אתה צריך לעשות זאת רק פעם אחת, אז אנחנו מפרסמים בפעם הראשונה. בפעמים הבאות, זה לא נדרש, הכל יסונכרן אוטומטית. הם הפעילו עבורי סנכרון במהירות, אבל לקח בערך 5 ימים עד שהחפץ הפך זמין ב-MavenCentral.

זה הכל, פרסמנו את החפץ שלנו ב-MavenCentral.

קישורים שימושיים

  • דוֹמֶה מאמר, פרסם רק דרך maven
  • הצגה מאגר סוג Sonatype
  • Jira סונטיפ שבו יוצרים את המשימה
  • דוגמה מאגר שבו הכל מוגדר

מקור: www.habr.com

קנה אירוח אמין לאתרים עם הגנת DDoS, שרתי VPS VDS 🔥 קנה אחסון אתרים אמין עם הגנת DDoS, שרתי VPS VDS | ProHoster