지속적인 제공을 위한 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 파이프라인은 우아하고 명확한 방식으로 지속적인 제공을 가능하게 합니다.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top