Рубрики
Uncategorized

Комплексное руководство по декларативному трубопроводу Jenkins [с примерами]

С последней версией Jenkins CI / CD создание декларативного трубопровода Дженкинса больше не является интенсивным или неустойчивым. С нашим историческим подходом мы стремимся вести вас к пониманию, …

Автор оригинала: Praveen Mishra.

Дженкинс-трубопровод — это решение автоматизации, которое позволяет создавать простые или сложные (шаблонные) трубопроводы через DSL, используемую в каждом трубопроводе. Jenkins предоставляет два способа разработки трубопровода-сценариев и декларативных. Традиционно Джэнькинс Джобс был создан с использованием Jenkins UI под названием Freestyle Jobs. В Jenkins 2.0 Jenkins представила новый способ создания заданий, используя технику, называемую трубопроводом в качестве кода. В Трубопровод как код Техника, задания создаются с использованием файла сценариев, который содержит шаги для выполнения заданием. В Дженкинс этот сценарный файл называется Jenkinsfile Отказ В этом блоге мы будем глубоко погружаться в декларативный трубопровод Дженкинса с помощью декларативных примеров трубопровода Дженкинса.

Давайте начнем с основы.

Что такое jenkinsfile?

Jenkinsfile это просто текстовый файл, обычно проверяющийся вместе с исходным кодом проекта в Git Repo. В идеале каждое заявление будет иметь свой собственный jenkinsfile.

Jenkinsfile можно написать в двух аспектах — Скрепление трубопровода синтаксис и декларативный синтаксис трубопровода

Что такое трубопровод Jenkins Scripted?

Дженкинс трубопроводы традиционно написаны как скриптовые трубопроводы. В идеале, конвейер сценариев хранится в Jenkins Webui в качестве файла Jenkins. Сценарий скрипта скрипта с скрипкой написан в Groovy.

  • Это требует знания Groovy Programming в качестве предварительного условия.
  • Jenkinsfile начинается со слов узел .
  • Может содержать стандартные конструкции программирования, такие как если бы блок, попробуйте блок, и т. Д.

Образец сценаризованного трубопровода

node {
    stage('Stage 1') {
        echo 'hello'
    }
}

Что такое декларативный трубопровод Дженкинса?

Декларативная подсистема трубопровода в трубопроводе Дженкинса относительно новая и обеспечивает упрощенный, самоутвержденный синтаксис сверху трубопроводных подсистем.

  • Последнее дополнение в технике создания трубопровода Дженкинс.
  • Дженкинс декларативный трубопровод должен использовать предопределенные конструкции для создания трубопроводов. Следовательно, это не гибко в качестве сценаризованного трубопровода.
  • Jenkinsfile начинается со слов трубопровод Отказ

Дженкинс Декларативный трубопровод должен стать предпочтительным способом создания работы Дженкинса, поскольку они предлагают богатый набор функций, поставляются с меньшим количеством кривой обучения и никакой предпосылки для изучения языка программирования, как Groovy, просто ради написания кода трубопровода.

Мы также можем проверить синтаксис декларативного конвейера перед запуском задания. Это помогает избежать много проблем выполнения с помощью сценария сборки.

Наш первый декларативный трубопровод

pipeline {
    agent any
    stages {
        stage('Welcome Step') {
            steps { 
                echo 'Welcome to LambdaTest'
            }
        }
    }
}

Мы рекомендуем VS Code IDE для написания сценариев трубопроводов Дженкинса, особенно при создании Дженкинс декларативных примеров трубопроводов.

Запуск вашего первого декларативного трубопровода

Теперь, когда вы хорошо знакомятся с основаниями трубопровода Дженкинса, пришло время погрузиться глубже. В этом разделе мы узнаем, как управлять декларативным трубопроводом Дженкинса. Вы можете обратиться к нашему Учебник трубопроводов Дженкинса для большего.

Давайте запустим наш декларативный трубопровод Дженкинса, шаг за шагом.

Шаг 1: Откройте домашнюю страницу Дженкинса ( http://localhost: 8080 в местном) и нажмите на Новый товар из меню левого бока.

Шаг 2: Введите Имя работы Дженкинса И выберите стиль как Трубопровод & нажмите Хорошо Отказ

Шаг 3: Прокрутите вниз до Трубопровод Раздел и скопируйте-вставьте свой первый декларативный код в стиле трубопровод снизу на текстовое поле скрипта.

Шаг 4: Нажмите на кнопку Сохранить и нажмите на Строить Сейчас из меню левого бока.

Мы можем увидеть этап бегущего по строительству на сцене в Этап Вид.

Шаг 5: Чтобы проверить журналы из задания построения, нажмите на любой этап и нажмите на Проверьте журналы кнопка. Или вы можете использовать Вывод консоли Из меню левого бока, чтобы увидеть журналы для сборки.

Вывод консоли

Вывод консоли

Дженкинс декларативный трубопровод синтаксис

В этом разделе мы рассмотрим наиболее часто используемые бланки Дженкинса декларативными трубопроводами или синтаксисом. Как правило, декларативные трубопроводы содержат один или несколько декларативных шагов или директив, как объяснено ниже.

трубопровод

Весь декларативный скрипт трубопровода должен быть написан внутри трубопровод блокировать. Это Обязательно блокировать.

pipeline {
}

агент Укажите, где должен работать задание по сборке Jenkins. Агент может быть на уровне трубопровода или на этапе. Обязательно определить агента.

Возможные значения-

  1. любой — Запустить работу или сцену на любом доступном агенте.
pipeline {
     agent any
}
  1. Нет — Не выделяйте любого агента во всем мире для трубопровода. Каждый этап должен указать свой собственный агент для запуска.
pipeline {
     agent none
}	
  1. этикетка — запустите работу в агенте, который соответствует данным здесь метке. Помните Jenkins ci/cd Может работать над архитектурой Master/Agent. Основные узлы могут делегировать задания для запуска узлов агента. Узлы на создании с учетом имени и этикетки для идентификации их позже.

E.G Все узлы Linux могут быть маркированы как Linux-машина

pipeline {
       agent {
           label 'linux-machine'
       }
}
  1. Докер — запустить работу в данном контейнере Docker

Образец можно найти здесь в Github Отказ

стадии

Этапы Блок представляет собой различные исполняемые этапные блоки. По крайней мере, один этапный блок является обязательным внутренним блоком этапов.

pipeline {
       agent {
           label 'linux-machine'
       }
     stages {
     }
}

сцена

Stage Block содержит фактические шаги выполнения. Этап блок должен быть определен в блоке этапов. Обязательно иметь хотя бы один ступенчатый блок внутри сценического блока. Также это обязательное имя каждого этапа блока, и это имя будет отображаться в Сцена Вид после того, как мы запустим работу.

В нижеприведенном ниже примере этап называется « Stead Chast »

pipeline {
       agent {
           label 'linux-machine'
       }
     stages {
         stage('build step') {
         }
     }
}

Образец можно найти здесь в Github Отказ

шаги

Шаги Блок содержит фактический шаг сборки. Обязательно иметь хотя бы один ступенчатый блок внутри этапного блока.

В зависимости от операционной системы агента (где работают Jenkins Joins), мы можем использовать оболочку, BAT и т. Д. Внутри команды шагов.

pipeline {
     agent any
     stages {
         stage('build step') {
              steps {
                 echo "Build stage is running"
              }
         }
     }
}

Сценарный трубопровод в Jenkins Job

Образец можно найти здесь в Github Отказ

параметры

Директива параметров обеспечивает способ работы Jenkins для взаимодействия с пользователями Jenkins CI/CD во время работы задания построения.

Параметр может быть из следующих типов — Строка, текст, BooleanParam, выбор & пароль

строка — Принимает значение типа строки из пользователя Jenkins.

Например. Строка (Имя: «Имя», Описание: «Пожалуйста, скажите мне свое имя?»)

текст — принимает многокомпонентное значение от jenkins user e.g.

Текст (имя: ‘desc’, Описание: «Опишите подробности работы»)

BooleanParam — принимает истинное/ложное значение от пользователя jenkins e.g.

BooleanParam (Имя: ‘Skip_test’, Описание: «Хотите пропустить беговые тестовые чехлы?»)

выбор — Пользователь Jenkins может выбрать один из вариантов предоставленного значения E.g.

Выбор (Имя: «Филиал», выбор: [«Master», «Dev»], Описание: «Выберите ветку»)

пароль — принимает секретный, как пароль от пользователя jenkins e.g.

Пароль (Имя: ‘sonar_server_pwd’, Описание: «Введите пароль Sonar»)

Давайте посмотрим на образец о том, как использовать директиву параметров-

pipeline {
    agent any
    parameters {
        string(name: 'NAME', description: 'Please tell me your name?')

        text(name: 'DESC', description: 'Describe about the job details')

        booleanParam(name: 'SKIP_TEST', description: 'Want to skip running Test cases?')

        choice(name: 'BRANCH', choices: ['Master', 'Dev'], description: 'Choose branch')

        password(name: 'SONAR_SERVER_PWD', description: 'Enter SONAR password')
    }
    stages {
        stage('Printing Parameters') {
            steps {
                echo "Hello ${params.NAME}"

                echo "Job Details: ${params.DESC}"

                echo "Skip Running Test case ?: ${params.SKIP_TEST}"

                echo "Branch Choice: ${params.BRANCH}"

                echo "SONAR Password: ${params.SONAR_SERVER_PWD}"
            }
        }
    }
}

Если в трубопроводе используется директива параметров, Jenkins CI/CD может ощущать, что ему необходимо принять ввод пользователя при запуске задания. Следовательно, Дженкинс изменит Построить сейчас Ссылка в левом меню для Построить с параметрами ссылка.

Когда мы нажимаем на Построить с параметрами Ссылка, Jenkins CI/CD позволит нам пропускать значения для параметров, которые мы настроили в декларативном конвейере.

Построить с параметрами

Как только мы введем значения каждого параметра, мы можем ударить построить кнопка для запуска задания.

скрипт

Блок сценария помогает нам запускать Groovy код внутри декларативного трубопровода Дженкинса.

pipeline {
    agent any
    parameters {
        string(name: 'NAME', description: 'Please tell me your name')
        choice(name: 'GENDER', choices: ['Male', 'Female'], description: 'Choose Gender')
    }
    stages {
        stage('Printing name') {
            steps {
                script {
                    def name = "${params.NAME}"
                    def gender = "${params.GENDER}"
                    if(gender == "Male") {
                        echo "Mr. $name"    
                    } else {
                        echo "Mrs. $name"
                    }
                }
            }
        }
   }
}

Сценарий Блок обернут внутри Шаги блокировать. В приведенном выше примере мы печатаем, как имя, пройденное в качестве параметра, совершаемого мистером или миссис, основанной на получении пола.

Мы использовали построить с параметрами пройти слова во время запуска работы.

среда

Пары значения ключевых значений, которые помогают пропускать значения на работу во время выполнения задания, снаружи jenkinsfile. Это один из способов внешней конфигурации.

Пример- Обычно Дженкинс Вакансии будет работать на отдельном сервере. Мы не можем быть уверены, что путь установки Java или Jmeter это этот сервер. Следовательно, это идеальные кандидаты, которые будут настроены в переменных среда и передаются во время запуска задания.

Метод 1: Настройка переменной среды в Jenkins CI/CD Portal

Шаг 1: Откройте URL jenkins сервера ( http://localhost: 8080 )

Шаг 2: Нажмите на управление Jenkins из меню левой боковой панели.

Шаг 3: Нажмите на Настроить систему Под конфигурацией системы.

Шаг 4: Прокрутите вниз до Глобальные свойства раздел. Это где мы добавим наши переменные среды.

Шаг 5: Нажмите на Добавить Кнопка в разделе «Переменные среды» и введите клавишу и значение.

Мы добавили путь установки Java под именем переменной Java_installation_path.

Шаг 6: Нажмите на Сохранить Кнопка.

См. Переменную среды в JenkinsFile Мы можем ссылаться на переменные среды в декларативном трубопроводе, используя $ {} синтаксис

pipeline {
    agent any
    stages {
        stage('Initialization') {
            steps {
                echo "${JAVA_INSTALLATION_PATH}"
            }
        }
   }
}

Способ 2: Создание и сосредоточение переменной среды в jenkinsfile

Мы можем создать параметры ключевых пар переменных среды под окружающая среда блокировать. Это Необязательно Блок под трубопроводом.

pipeline {
    agent any
    environment { 
        DEPLOY_TO = 'production'
    }
    stages {
        stage('Initialization') {
            steps {
                echo "${DEPLOY_TO}"
            }
        }
    }
  }

Метод 3: Инициализировать переменные среды с использованием SH Scripts в JenkinsFile

Скажем, нам нужен временная метка, когда работа будет запускаться для целей регистрации. Мы можем создать переменную среды, которая может удерживать временную метку. Но как это инициализировать это?

Мы можем использовать сценарий Shell для получения текущего времени TimeStamp и назначить его переменной среды.

Пример-

Следующая команда будет печатать дату и время в оболочке

>  date '+%A %W %Y %X' 
Tuesday 03 2021 22:03:31

Давайте посмотрим, как использовать вышеуказанную команду для инициализации переменной среды в JenkinsFile.

pipeline {
    agent any
    stages {
        stage('Initialization') {
            environment { 
                   JOB_TIME = sh (returnStdout: true, script: "date '+%A %W %Y %X'").trim()
            }
            steps {
                sh 'echo $JOB_TIME'
            }
        }
    }
}

returnstdout: True делает SH STAGE, возвращая выход команды, чтобы вы могли назначить ее переменной.

Образец можно найти здесь в Github Отказ

Учетные данные () — это специальный метод, который можно использовать внутри блока среды. Этот метод помогает загрузке учетных данных, определенных в конфигурации Jenkins.

Давайте увидим это с примером. Сначала позволяет настроить учетные данные в Jenkins CI/CD-

Создание учетных данных в Портале Дженкинса

Шаг 1: Откройте URL jenkins сервера ( http://localhost: 8080 )

Шаг 2: Нажмите на Управляйте Дженкинсом из меню левой боковой панели.

Шаг 3: Нажмите на Управлять Учетные данные под Безопасность Отказ

Шаг 4: Нажмите на Глобальный гиперссылка.

Шаг 5: Нажмите на Add Учетные данные из меню левого бока.

Для демонстрации позвольте мне использовать следующие значения

  • Добрый — Имя пользователя с паролем
  • Область применения — глобальная
  • Имя пользователя — admin.
  • Пароль — root123.
  • ID — My_Secret.
  • Описание — секрет доступа к файлам сервера

Шаг 6: Нажмите на Хорошо кнопка. Теперь наши полномочия настроены.

Ссылаясь на учетные данные в jenkinsfile

Мы можем использовать специальный метод под названием учетные данные () Для загрузки учетных данных мы настроили. Нам нужно использовать идентификатор, который мы использовали при настройке учетных данных для загрузки определенных учетных данных.

Пример- учетные данные (‘my_secret’)

Обратиться к именному именному пользователям, добавьте слово _Usr Для переменной мы присваиваем учетные данные () вывода и добавления слова _PSW Чтобы получить пароль.

Пример — давайте загрузим учетные данные в My_cred Переменная с использованием учетные данные (‘my_secret’) метод. Нам нужно добавить _Usr (мой \ _cred \ _usr) ** & ** \ _ psw (my_cred_psw) Переменную My_cred, чтобы получить имя пользователя и пароль.

pipeline {
    agent any
  environment { 
   	MY_CRED = credentials('MY_SECRET') 
    }
    stages {
        stage('Load Credentials') {
            steps {
                echo "Username is $MY_CRED_USR"
                echo "Password is $MY_CRED_PSW"
            }
        }
    }
}

Интересно, что jenkins печатает имя пользователя и пароль как ****, чтобы избежать случайной утечки учетных данных.

когда

Действует, как если бы состояние решить, запускать конкретный этап или нет. Его Необязательно блокировать.

  1. Когда блокировать
pipeline {
     agent any
     stages {
         stage('build') {
              when {
                  branch 'dev'             
              }
              steps {
                 echo "Working on dev branch"
              }
         }
     }
}
  1. Когда блок с использованием Groovy выражение
pipeline {
     agent any
     stages {
         stage('build') {
              when {
                  expression {
                     return env.BRANCH_NAME == 'dev';
                  }             
              }
              steps {
                 echo "Working on dev branch"
              }
         }
     }
}
  1. Когда блок с Переменные среды
pipeline {
    agent any
    environment { 
        DEPLOY_TO = 'production'
    }
    stages {
        stage('Welcome Step') {
            	when { 
    environment name: 'DEPLOY_TO', value: 'production'
}
            steps { 
                echo 'Welcome to LambdaTest'
            }
        }
    }
}
  1. Когда блок с Несколько условий и все условия должны быть удовлетворены
pipeline {
    agent any
    environment { 
        DEPLOY_TO = 'production'
    }
    stages {
        stage('Welcome Step') {
            when { 
                allOf { 
                    branch 'master'; 
                    environment name: 'DEPLOY_TO', value: 'production'
                } 
            }
            steps { 
                echo 'Welcome to LambdaTest'
            }
        }
    }
}
  1. Когда блок с Несколько условий и любой из данных условий должны быть удовлетворены
pipeline {
    agent any
    environment { 
        DEPLOY_TO = 'production'
    }
    stages {
        stage('Welcome Step') {
            when { 
                anyOf { 
                    branch 'master';
                    branch 'staging' 
                } 
            }
            steps { 
                echo 'Welcome to LambdaTest'
            }
        }
    }
}

Образец можно найти здесь в Github Отказ

инструменты

Этот блок позволяет нам добавлять предварительно настроенные инструменты, такие как Maven или Java на путь нашей работы. Это Необязательно блокировать.

Чтобы использовать любой инструмент, они должны быть предварительно настроен под Конфигурация глобальных инструментов раздел. Для этого примера давайте посмотрим, как настроить Maven. Вы также можете обратиться к нашему Учебник интеграции Jenkins Maven для дополнительной информации.

Шаг 1: Откройте URL jenkins сервера ( http://localhost: 8080 )

Шаг 2: Нажмите на Управляйте Дженкинсом из меню левой боковой панели.

Шаг 3 : Нажмите на Конфигурация глобальных инструментов Под конфигурацией системы.

Шаг 4: Прокрутите вниз до Maven Раздел и нажмите на Установки Maven Отказ

Шаг 5: Нажмите на Добавить Maven кнопка. Введите следующие значения в конфигурации.

  • Имя — Maven 3.5.0
  • Maven_home — введите путь установки Maven в местном

В качестве альтернативы мы можем загрузить Maven из Интернета вместо того, чтобы указывать на локальный путь установки, включив установку автоматически.

Шаг 6: Нажмите на Добавить установщик Кнопка и выберите Установите из Apache Отказ

Шаг 7: Выберите версию Maven для загрузки. Мы выбрали версию Maven 3.6.3 .

Шаг 8: Нажмите на Сохранить кнопка.

Обратитесь к инструменту Maven в трубопроводе в блоке инструментов с именем, которое мы использовали при настройке в конфигурации глобальных инструментов (Maven_Path в этом примере).

pipeline {
    agent any
    tools {
        maven 'MAVEN_PATH' 
    }
    stages {
         stage('Load Tools') {
              steps {
                 sh "mvn -version"
              }
         }
     }
}

Образец можно найти здесь в Github Отказ

Консольный вывод

Запустите работу, и мы должны увидеть отклик команд MVN -Version в консоли

Точно так же мы также можем настроить и использовать инструменты, такие как Java, Gradle, Git Etc из блока инструментов в трубопроводном коде.

параллельно

Параллельные блоки позволяют нам Запустите несколько этап блоков одновременно . Он идеально подходит для параллелизных этапов, которые могут бежать самостоятельно. Мы можем определить агенты для каждого этапа в параллельном блоке, поэтому каждый этап будет работать на собственном агенте.

Пример- Когда мы хотим запустить элемент сценария в Windows Agent & другой сценарий в агенте Linux в рамках сборки, мы можем заставить их выполнять одновременно с использованием параллельных блоков.

pipeline {
    agent any
    stages {
           stage('Parallel Stage') {
              parallel {
                stage('windows script') {
                    agent {
                        label "windows"
                    }
                    steps {
                        	echo "Running in windows agent"
    bat 'echo %PATH%'
                    }
                }
                stage('linux script') {
                    agent {
                        label "linux"
                    }
                    steps {
                       sh "Running in Linux agent"
                    }
                }
             }
        }
    }
}

Образец можно найти здесь в Github Отказ

Почта

пост Блок содержит дополнительные действия, которые должны выполняться по завершении выполнения трубопровода. Он может содержать один или многие из следующих условных блоков — всегда, изменены, прерваны, неудача, успех, нестабильные и т. Д.

Почтовые условия блока

всегда — Запустите этот почтовый блок независимо от статуса выполнения трубопровода Изменено — Запустите этот почтовый блок, только если статус выполнения трубопровода отличается от предыдущего запуска сборки. E.G., сборка не удалась в более раннем пробеге и успешно запущена на этот раз. прерван — Если сборка прерывается в середине прогона. Обычно из-за ручной остановки сборки BEAD Ошибка — Если статус сборки неисправен Успех — Если сборка успешно побежала нестабильно — построить успешно, но не здоров. Например. На конкретном запуске сборки тестируемые дела успешно работали, но тестовое покрытие% меньше, чем ожидалось, то сборка может быть помечена как нестабильные

Пример-

pipeline {
     agent any
     stages {
         stage('build step') {
              steps {
                 echo "Build stage is running"
              }
         }
     }
     post {
         always {
             echo "You can always see me"
         }
         success {
              echo "I am running because the job ran successfully"
         }
         unstable {
              echo "Gear up ! The build is unstable. Try fix it"
         }
         failure {
             echo "OMG ! The build failed"
         }
     }
}

Образец можно найти здесь в Github Отказ

Маркировка строить как нестабильные

Существуют сценарии, где мы не хотим отмечать сборку как неудачу, но хочу пометить построить как нестабильно.

Пример- Когда охват теста, не пересекает пороговое значение, которое мы ожидаем, мы можем пометить сборку как Нестабильный Отказ

pipeline {
    agent any
    tools {
        maven 'MAVEN_PATH'
        jdk 'jdk8'
    }
    stages {
        stage("Tools initialization") {
            steps {
                sh "mvn --version"
                sh "java -version"
            }
        }
        stage("Checkout Code") {
            steps {
                git branch: 'master',
                url: "https://github.com/iamvickyav/spring-boot-data-H2-embedded.git"
            }
        }
        stage("Building Application") {
            steps {
               sh "mvn clean package"
            }
        }
        stage("Code coverage") {
           steps {
               jacoco(
                    execPattern: '**/target/**.exec',
                    classPattern: '**/target/classes',
                    sourcePattern: '**/src',
                    inclusionPattern: 'com/iamvickyav/**',
                    changeBuildStatus: true,
                    minimumInstructionCoverage: '30',
                    maximumInstructionCoverage: '80')
               }
           }
        }
 }

Образец можно найти здесь в Github Отказ

jacoco () Это специальный метод, который помогает нам настроить отчеты Jacoco, включая минимальный и максимальный порог покрытия. В приведенном выше примере, Min Casting (миниминструкционная проверка) установлена в виде 30 и максимального покрытия (максимально раскрытие), установлена в 80.

Так что если охват кода

Менее 30 — Сборка будет помечена как неудача. Между 30 и 80 — Сборка будет помечена как нестабильные. Выше 80 — Сборка будет помечена как успех.

триггеры

Вместо того, чтобы запустить сборку вручную, мы можем настроить сборку для запуска в определенных временных интервалах с использованием блока триггеров. Мы можем использовать специальный метод cron () в блоке триггеров, чтобы настроить график сборки.

Понимание Cron

Конфигурация CRON содержит 5 полей, представляющих минуту (0-59), час (0-23), день месяца (1-31), месяц (1-12), день недели (0-7)

Пример-

Каждые 15 минут — H/15 * * * * Каждые 15 минут, но только в период с понедельника и пятница — H/15 * * * 1-5

pipeline {
    agent any
    triggers {
        cron('H/15 * * * *')
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

Образец можно найти здесь в Github Отказ

Заключение

В этом блоге мы сделали углубленное погружение в примеры декларативных трубопроводов Дженкинса и их использование. Вместо того, чтобы настроить шаги сборки с использованием UI в удаленном портале Jenkins, мы всегда рекомендуем вам предпочитать создание JenkinsFile с декларативным синтаксисом трубопровода. Jenkinsfile, поскольку часть исходного кода приложения обеспечивает больше шагов CI/CD для разработчиков. Это лучший способ максимально использовать Jenkins CI/CD и все функции, которые он должен предложить!

Счастливое здание и тестирование!

Оригинал: «https://www.codementor.io/@prav33nmishra/comprehensive-guide-to-jenkins-declarative-pipeline-with-examples-1iq9m92ir6»