지속적인 제공을 위한 Nexus Repository 및 Jenkins

새로운 기능의 개발 속도에 대한 증가하는 요구를 충족시키기 위해서는 더 빠르게 구현되어야 합니다. 하지만 이는 동전의 한 면일 뿐입니다. 이러한 모든 기능을 프로덕션에 투입해야 합니다. 배포는 종종 수동으로 수행되므로 오류가 발생하기 쉽고 리소스가 정체되며 시간이 오래 걸릴 수 있습니다. 완벽한 솔루션이 제공됩니다 오토메이션 on – 지속적 전달이라고 합니다. 때때로 또한 사이 지속적 전달 그리고 지속적인 배포 그러나 이것은 기사의 핵심에 중요하지 않은 다면적인 논쟁입니다.

지속적인 전달은 아티팩트 유형에 따라 다른 의미를 가질 수 있으며 이를 달성하기 위해 유사하게 다른 도구를 사용할 수 있습니다. Jenkins Pipelines의 장점은 매우 간단하고 모듈식으로 구현된다는 것입니다. 이 기사에서는 몇 줄의 Groovy 코드로 Nexus 리포지토리에 Java 아티팩트를 지속적으로 제공하는 방법을 보여주기 위해 두 가지 실용적인 예제를 사용합니다.

  • 첫 번째 예는 오픈 소스 Java 라이브러리는 먼저 Jenkins GitHub 리포지토리에 푸시될 때 빌드되고 테스트된 다음 SonarCloud로 분석되고 Maven Central에 배포됩니다(그림 1 참조).
  • 두 번째 예는 엔터프라이즈 컨텍스트에서 제공되며 SCM Manager의 Git 리포지토리로 푸시될 때 Cloudogu EcoSystem을 사용하여 Jenkins에서 Java 웹 애플리케이션을 자동으로 빌드 및 테스트하고 SonarQube에서 분석한 후 최종적으로 프라이빗 Nexus 리포지토리에 배포하는 방법을 보여줍니다(그림 참조). 2).

예제의 인프라는 다르지만 두 경우 모두 Jenkins 관로사용할 코드.

(PlantUML 원본 다이어그램)

Maven Central에 지속적 전달

다음에서는 오픈 소스 Java 라이브러리를 예로 사용하여 Maven Central에 따라 지속적 전달을 구현하는 방법을 보여줍니다. 완성된 지속적 전달 파이프라인(빌드, 단위 및 통합 테스트, 정적 코드 분석 및 배포 포함)은 Jenkins 파이프라인 Groovy DSL(스크립트 구문)의 100줄 미만으로 Jenkins 파일에서 구현할 수 있습니다. 목록 1은 명령 버스 라이브러리의 Jenkinsfile을 기반으로 하는 예제를 보여줍니다. 명확성을 위해 이 기사에서는 다소 축약되었습니다.

@Library('github.com/cloudogu/[email protected]')
import com.cloudogu.ces.cesbuildlib.*

node {

  Maven mvn = new MavenWrapper(this)

  catchError {

    stage('Checkout') {
      checkout scm
    }

    initMaven(mvn)

    stage('Build') {
      mvn 'clean install -DskipTests'
    }

    stage('Unit Test') {
      mvn 'test'
    }

    stage('Integration Test') {
      mvn 'verify -DskipUnitTests'
    }

    stage('Static Code Analysis') {
      def sonarQube = new SonarCloud(this, [sonarQubeEnv: 'sonarcloud.io-cloudogu'])

      sonarQube.analyzeWith(mvn)

      if (!sonarQube.waitForQualityGateWebhookToBeCalled()) {
        currentBuild.result ='UNSTABLE'
      }
    }

    stage('Deploy') {
      if (preconditionsForDeploymentFulfilled()) {

        mvn.useDeploymentRepository([id: 'ossrh', url: 'https://oss.sonatype.org/',
                                     credentialsId: 'mavenCentral-acccessToken', type: 'Nexus2'])

        mvn.setSignatureCredentials('mavenCentral-secretKey-asc-file', 'mavenCentral-secretKey-Passphrase')

        mvn.deployToNexusRepositoryWithStaging()
      }
    }
  }

  junit allowEmptyResults: true, testResults: '**/target/surefire-reports/TEST-*.xml, **/target/failsafe-reports/*.xml'

  mailIfStatusChanged(new Git(this).commitAuthorEmail)
}

boolean preconditionsForDeploymentFulfilled() {
  if (isBuildSuccessful() &&
      !isPullRequest() &&
      shouldBranchBeDeployed()) {
    return true
  } else {
    echo "Skipping deployment because of branch or build result: currentResult=${currentBuild.currentResult}, " +
      "result=${currentBuild.result}, branch=${env.BRANCH_NAME}."
    return false
  }
}

private boolean shouldBranchBeDeployed() {
  return env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'develop'
}

private boolean isBuildSuccessful() {
  currentBuild.currentResult == 'SUCCESS' &&
    // Build result == SUCCESS seems not to set be during pipeline execution.
    (currentBuild.result == null || currentBuild.result == 'SUCCESS')
}

void initMaven(Maven mvn) {

  if ("master".equals(env.BRANCH_NAME)) {

    echo "Building master branch"
    mvn.additionalArgs = "-DperformRelease"
    currentBuild.description = mvn.getVersion()
  }
}

목록 1

Jenkins 파일에는 5개의 소위 단계가 포함되어 있습니다.

  • Checkout – Git 리포지토리에서 코드를 가져옵니다.
  • 빌드, 단위 테스트 및 통합 테스트 – Maven을 사용하여 코드를 빌드하고 이에 대한 단위 및 통합 테스트를 실행합니다.
  • 정적 코드 분석 – SonarQube(여기서는 퍼블릭 인스턴스 SonarCloud)의 도움으로 정적 코드 분석을 실행하고 정의된 품질 목표에 대해 기록된 메트릭을 확인합니다.
  • 배포 – 오류가 발생하지 않은 경우 Nexus Repository(여기서는 Sonatype에서 공개적으로 제공하는 “Maven Central” 인스턴스)에 아티팩트를 배포합니다.

Jenkins 공유 라이브러리 ces-build-lib는 파이프라인에서 사용됩니다. 여기에는 Maven(Nexus 리포지토리 포함), Git 및 SonarQube용 재사용 가능한 빌딩 블록이 포함되어 있습니다. Jenkins 공유 라이브러리를 사용하면 일반 애플리케이션 개발에서 라이브러리를 통합할 때와 동일한 이점을 얻을 수 있습니다. 특히 ces-build-lib는 Maven Central에 배포할 때 서명 및 스테이징을 처리하고 SonarCloud를 통해 풀 요청에 대한 주석을 시작하므로 대부분의 복잡성을 처리합니다.

모든 브랜치(기능 브랜치 및 풀 리퀘스트 포함)는 자동화된 품질 관리를 거치지만 배포는 보다 안정적인 브랜치 마스터 및 개발(Git Flow 기반)로 제한됩니다. 푸시에 의해 배포가 트리거됩니다.

제시된 파이프라인이 Jenkins에서 실행되기 위해서는 Jenkins에 다음이 존재해야 합니다.

  • “파이프라인: GitHub Groovy 라이브러리” 플러그인. GitHub에서 즉시 공유 라이브러리를 로드합니다.
  • ID가 sonarcloud.io-cloudogu인 구성된 SonarQube 인스턴스와 URL, 인증 토큰 및 SonarCloud에 대해 구성된 조직. Jenkins가 SonarQube에서 비동기식으로 계산한 Quality Gate Status를 알기 위해서는 /sonarqube-webhook/ 아래 Jenkins 인스턴스의 SonarCloud에 webhook을 생성해야 합니다. SonarCloud도 GitHub 문제에 대해 의견을 제시하려면 GitHub용 SonarCloud 애플리케이션이 GitHub 조직에 설치되어 있어야 합니다.
  • 비밀 텍스트 자격 증명 mavenCentral-accessToken으로 oss.sonatype.org에 대한 사용자 액세스 토큰(Central Staging Repository에서 Maven Central로 릴리스).
  • ASC 파일의 개인 키(비밀 파일 자격 증명 mavenCentral-secretKey-asc-file). 이는 Maven Central의 아티팩트에 서명하는 데 사용됩니다.
  • 개인 키의 암호(Secret Text Credential mavenCentral-secretKey 암호). 자세한 내용은 Maven Central 설명서를 참조하십시오.

예제는 이 Jenkins 서버에서 실제로 볼 수 있습니다.

온프레미스 Nexus 리포지토리에 지속적으로 제공

(OkabtUML 원본 다이어그램)

오픈 소스 라이브러리와 동일한 워크플로를 자체 인프라의 엔터프라이즈 환경에서도 사용할 수 있습니다. 그림 2는 GitHub 대신 SCM Manager, Maven Central 대신 자체 Nexus Repository, SonarCloud 대신 SonarQube 등 가능한 도구 선택을 보여줍니다. 다음을 통해 이러한 도구와 더 많은 도구를 얻을 수 있습니다. Cloudogu 생태계 버튼을 누르면 완전히 자동으로 사전 구성되고 싱글 사인온이 제공됩니다.

이 환경에서는 첫 번째 예제와 거의 동일한 Jenkins 파이프라인을 사용할 수 있습니다. 이것은 두 번째 예제 cloudogu/spring-petclinic의 Jenkins 파일에 표시됩니다(목록 2 참조). 이것은 Jenkins 파일을 사용하여 지속적인 제공을 포함하도록 확장된 Java 웹 애플리케이션의 대표적인 예입니다.

@Library('github.com/cloudogu/[email protected]')
import com.cloudogu.ces.cesbuildlib.*

properties([
        disableConcurrentBuilds()
])

node {

    String cesFqdn = findHostName()
    String cesUrl = "https://${cesFqdn}"

    Maven mvn = new MavenWrapper(this)

    catchError {

        stage('Checkout') {
            checkout scm
        }

        stage('Build') {
            mvn 'clean package -DskipTests'
        }

        String jacoco = "org.jacoco:jacoco-maven-plugin:0.8.1"
        parallel(
                test: {
                    stage('Unit Test') {
                        mvn "${jacoco}:prepare-agent test ${jacoco}:report"
                    }
                },
                integrationTest: {
                    stage('Integration Test') {
                        mvn "${jacoco}:prepare-agent-integration failsafe:integration-test failsafe:verify ${jacoco}:report-integration"
                    }
                }
        )

        stage('Static Code Analysis') {
            def sonarQube = new SonarQube(this, [usernamePassword: 'jenkins-sonar', sonarHostUrl: "${cesUrl}/sonar"])

            sonarQube.analyzeWith(mvn)
        }

        stage('Deploy') {
            mvn.useDeploymentRepository([id: cesFqdn, url:  "${cesUrl}/nexus", credentialsId: 'jenkins-nexus', type: 'Nexus3'])

            mvn.deployToNexusRepository()
        }
    }

    junit allowEmptyResults: true, testResults: '**/target/failsafe-reports/TEST-*.xml,**/target/surefire-reports/TEST-*.xml'
}

목록 2

모든 프로젝트가 다르므로 파이프라인에도 약간의 차이가 있습니다. 첫 번째 예와 비교하여 다음과 같은 관련 차이점이 있습니다.

  • 여기서 SonarQube 및 Nexus에 대한 URL은 Jenkins에 상대적입니다(Cloudogu EcoSystem 덕분에 유지 관리가 더 쉽습니다).
  • 더 빠른 피드백을 위해 단위 및 통합 테스트가 동시에 실행됩니다.
  • Maven Central과 달리 배포 단계에서는 스테이징 리포지토리를 사용하지 않습니다.

일반적으로 이 예제는 조금 더 간단하므로 Jenkins는 파이프라인을 실행하는 데 덜 필요합니다.

  • “파이프라인: GitHub Groovy Libraries” 플러그인은 첫 번째 예와 같이,
  • 암호 자격 증명이 있는 사용자 이름 jenkins-sonar, SonarQube의 기술 사용자 및
  • 암호 자격 증명이 있는 사용자 이름 jenkins-nexus를 Nexus의 기술 사용자에게 전달합니다.
Cloudogu 생태계

Cloudogu 생태계의 장점을 확신하십시오. 사용 이젠 공짜 최신 DevOps 플랫폼.

플랫폼으로

결론

이 문서는 Nexus 리포지토리에 Java 아티팩트를 얼마나 쉽게 지속적으로 전달할 수 있는지 보여줍니다. 원하는 도구는 오픈 소스 및 엔터프라이즈와 같은 다양한 응용 프로그램에서 사용할 수 있습니다. 물론 #DevSecOps 와 같이 Sonatype Lifecycle 또는 부하 테스트를 통한 취약점 분석을 통해 품질 보증을 확장할 수도 있습니다. 특정 도구 선택에 관계없이 Jenkins 파이프라인은 우아하고 명확한 방식으로 지속적인 제공을 가능하게 합니다.

About admin

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다