14 Mart 2022 Pazartesi

Jenkinsfile Scripted Pipeline - Eski Yöntem

Giriş
Groovy DSL kullanılır. Açıklaması şöyle
Jenkinsfiles, using a domain specific language based on the Groovy programming language, are persistent files that model delivery pipelines “as code”, containing the complete set of encoded steps (steps, nodes, and stages) necessary to define the entire application life-cycle
Açıklaması şöyle. Sadece stage'lerden ibarettir
Scripted pipelines, on the other hand, always begin with the word node
...
Scripted pipelines use Groovy code and references to the Jenkins pipeline DSL within the stage elements without the need for steps.
Scripted pipeline tercih edilmemeli deniliyor. Açıklaması şöyle
The development community found that pipeline builders with strong Java and Groovy skills, but little experience with Jenkins, would often write complicated Groovy code to add functionality that's already available through the Jenkins DSL.
Script Söz Dizimi
1. Parametre Tanımlama
Örnek
Şöyle yaparız
properties([
  parameters([
    booleanParam(
      name: 'ARTIFACTORY_PUBLISH',
      defaultValue: false,
      description: 'If checked, the publish step is executed'
    ),
    stringParam(
      name: 'CUSTOMER',
      defaultValue: "",
      description: 'the customer\'s specific packages to deploy'
    )
  ])
])
Boolean parametreye şöyle erişiriz
def shouldDeployToArtifactory() {
  return "${params.ARTIFACTORY_PUBLISH}" == "true"
}
Boolean parametreye şöyle erişiriz
if ("${params.CUSTOMER}" != "") {
  ...
}
2. Node Tanımlama
Örnek
En basit hali şöyle
node {
  // groovy script
}
Örnek
Şöyle yaparız
node {
  stage('Build') {
  }
  stage('Test') {
  }
  stage('Deploy') {
  }
}
Örnek
Şöyle yaparız
node ('node-1') {
  stage('Source') {
    git 'https://github.com/digitalvarys/jenkins-tutorials.git''
  }
  stage('Compile') {
    def gradle_home = tool 'gradle4'
    sh "'${gradle_home}/bin/gradle' clean compileJava test"
  }
}
checkout
class olarak bir sürü farklı seçenek verilebilir. Bir liste burada

Git Açıklamaları
İki kullanım şekli var
git branch: "${branch}",credentialsId: '...',url: 'git@github.com:...'
veya
checkout([...])
extensions açıklaması şöyle
Extensions add new behavior or modify existing plugin behavior for different uses. Extensions help users more precisely tune plugin behavior to meet their needs.

Extensions include:
- Clone extensions modify the git operations that retrieve remote changes into the agent workspace. The extensions can adjust the amount of history retrieved, how long the retrieval is allowed to run, and other retrieval details.
- Checkout extensions modify the git operations that place files in the workspace from the git repository on the agent. The extensions can adjust the maximum duration of the checkout operation, the use and behavior of git submodules, the location of the workspace on the disc, and more.
Changelog extensions adapt the source code difference calculations for different cases.
- Tagging extensions allow the plugin to apply tags in the current workspace.
- Build initiation extensions control the conditions that start a build. They can ignore notifications of a change or force a deeper evaluation of the commits when polling.
- Merge extensions can optionally merge changes from other branches into the current branch of the agent workspace. They control the source branch for the merge and the options applied to the merge.
Örnek
Şöyle yaparız. Burada Git kullanılıyor ve shallow olmaması isteniyor
stage("SCM checkout") {
  sendSlackGreenNotification("Build ${env.BUILD_NUMBER} started for  ${env.JOB_NAME}.  
                              Details: ${env.BUILD_URL}")
  checkout([
    $class: 'GitSCM',
    branches: scm.branches,
    doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
    extensions: scm.extensions + [
      [$class: 'WipeWorkspace'],
      [$class: 'PruneStaleBranch'],
      [$class: 'CloneOption', noTags: false, reference: '', shallow: false], 
      [$class: 'GitLFSPull'],
      [$class: 'LocalBranch']
    ],
    submoduleCfg: [],
    userRemoteConfigs: scm.userRemoteConfigs
  ])
}

def sendSlackGreenNotification(message) {
  notifySlack(message, "good")
}
Örnek
Şöyle yaparız. Burada shallow olması isteniyor ve depth belirtiliyor.
checkout([
  $class: 'GitSCM',
  branches: [[name: "*/${params.BRANCH}"]],
  extensions: [[
    $class: 'CloneOption',
    shallow: true,
    depth:   1,
    timeout: 30
  ]],
  userRemoteConfigs: [[
    url:           params.SCM_URL,
    credentialsId: 'MY_GIT_CREDENTIALS'
  ]]
])
Örnek
Şöyle yaparız
String branch = "master"
String Registry = "alicanuzun/springboot"
String currentContext = "minikube"
String serviceName = "springboot"
String environment = "default"
String chartPath = "apps/springboot"

timestamps() {
  node(label: 'master') {
    stage('Git Checkout') {
      git branch: "${branch}",
        credentialsId: 'SpringBoot-GitHub',
        url: 'git@github.com:alican-uzun/springboot'
    }
    stage("Docker Build") {
      sh "docker build -t alicanuzun/springboot ."
    }
    stage("Login to DockerHub"){
      withCredentials([usernamePassword(credentialsId: 'dockerhub-creds',
       usernameVariable: 'DOCKERHUB_USERNAME', passwordVariable: 'DOCKERHUB_PASSWORD')]){
       sh('docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD')
      }
    }
    stage("Push Image to DockerHub"){
      sh """
        docker tag ${Registry}:latest ${Registry}:prod-${currentBuild.number}
        docker push ${Registry}:prod-${currentBuild.number}
        """
    }
    stage('Helm Chart Git Checkout'){
      git branch: "${branch}",
        credentialsId: 'Helm-Charts-GitHub',
        url: 'git@github.com:alican-uzun/helm-charts'
    }
    stage("Deploy on Minikube Cluster"){
      sh  "helm upgrade --install " +
        "${serviceName} ${chartPath} -f ${chartPath}/values.yaml -n ${environment} " + 
        "--set image.tag=prod-${currentBuild.number} " +
        "--set image.repository=${Registry} " +
        "--namespace=${environment} "
        "--kube-context=${currentContext}"
    }
  }
}
env
BRANCH_NAME Alanı
Örnek
Şöyle yaparız
def isDevelopBranch() {
  def current_branch = env.BRANCH_NAME
  echo 'Current branch is: ' + current_branch

  return current_branch != null && current_branch.startsWith("develop")
}

def isReleaseBranch() {
  def current_branch = env.BRANCH_NAME
  echo 'Current branch is: ' + current_branch

  return current_branch != null && current_branch.startsWith("release/")
}

def shouldDeployToArtifactory() {
  return isDevelopOrReleaseBranch() || "${params.ARTIFACTORY_PUBLISH}" == "true"
}
stage('Build') {
  ...
  if (shouldDeployToArtifactory()) {
    stage("Push to Artifactory") {
    echo "Publishing to Artifactory..."
    withCredentials([usernamePassword(credentialsId: 'ARTIFACTORY_PUBLISH',
                                      passwordVariable: 'ARTIFACTORY_PASSWORD', 
                                      usernameVariable: 'ARTIFACTORY_USER')]) {
      runGradleSteps("publish")
    }
  }
}
Curl Kullanımı
Örnek
Şöyle yaparız
def healthTest(deploymentIp, envName) {
  STATUS_CODE= sh (
    script: "curl -sL -x snort-us-central1-a.gcp.foo.com:3128 -w '%{http_code}' 
      $deploymentIp:10509 -o /dev/null \
      --max-time 15",
      returnStdout: true
    )
  echo "Status code $STATUS_CODE"
  if(STATUS_CODE == "200") {
    echo "$envName environment has come up and ready to use"
  } else {
    currentBuild.result = 'ABORTED'
    error("$envName hasn\'t come up. Health test failed")
  }
}
Slack Kullanımı
Örnek
Elimizde şöyle bir kod olsun
def sendSlackGreenNotification(message) {
  notifySlack(message, "good")
}

def sendSlackRedNotification(message) {
  notifySlack(message, "danger")
}

def notifySlack(text, color) {
  def slackURL = "https://foo.slack.com/services/hooks/jenkins-ci/12345"
  def slack_channel = "foo-jenkins"
  def payload = JsonOutput.toJson([text      : text,
                                   channel   : slack_channel,
                                   username  : "jenkins",
                                   icon_emoji: ":jenkins:",
                     		   color  : color])
    sh "curl -X POST -x snort-us-central1-a.gcp.foo.com:3128 --data-urlencode \'payload=${payload}\' ${slackURL}"
}
Şöyle yaparız
stage("My Stage") {
  sendSlackGreenNotification("Build ${env.BUILD_NUMBER} started for ${env.JOB_NAME} at 
    ${env.BUILD_URL}")
  ...
  sendSlackGreenNotification("Completed for ${env.JOB_NAME}")
}
sh Kullanımı
Örnek
Şöyle yaparız
def execute_on_gcp(envName) {
  withEnv(['http_proxy=', 'https_proxy=']) {
    def CLUSTER_NAME = "mycluster"
     def PROJECT_ID = "product-foo"

    sh "gcloud auth activate-service-account --key-file=.gcp/product-foo.json"
    sh "gcloud container clusters get-credentials ${CLUSTER_NAME} --zone us-central1-a --project ${PROJECT_ID}"
    sh "kubectl apply -f .gcp/foo-db-${envName}.yml"
    sh "kubectl apply -f .gcp/foo-farm-${envName}.yml"
    DB_POD_NAME = sh(
      script: "kubectl get pods --all-namespaces | grep rw60-db-${envName} | awk '{print \$2}'",
      returnStdout: true
    ).trim();
    DB_POD_IP = sh(
      script: "kubectl exec ${DB_POD_NAME} -- cat /etc/hosts | grep rw60-db-${envName} | awk '{print \$1}'",
      returnStdout: true
    ).trim();
    try {
      sh "kubectl exec ${DB_POD_NAME} -- su -c \"nohup /oracle-data/data-import.sh\""
    } catch(err) {
      echo "Errors are expected on data import"
    }
  }
}
withEnv
Açıklaması şöyle
You can use withEnv to set environment variables inside of your pipeline. The pipeline then makes the variables accessible to external processes spawned inside it.
Örnek
Şöyle yaparız
node {
  withEnv(['MY_NAME_IS=Eric']) {
    sh echo 'My name is $MY_NAME_IS'
  }
}





Hiç yorum yok:

Yorum Gönder