Вопрос или проблема
Моя общая цель состоит в том, чтобы создать параметр сборки в Jenkins, который будет выпадающим списком только для веток релиза. Я уже некоторое время занимаюсь этим и знаю, что существует множество способов это сделать. Позвольте мне пройтись по нескольким методам, которые я пробовал, и объяснить, почему конкретные методы не сработают в моем сценарии, и почему тот, который я пытаюсь реализовать, скорее всего, более подходит для моего приложения.
Моя текущая попытка
На данный момент у меня есть параметр Active Choice. (Другие, такие как Extensible Choice и Extended Choice, тоже подходят), и в нём есть мой groovy скрипт. Он работает именно так, как мне нужно, но я вынужден вводить в открытом тексте свое имя пользователя и пароль для git.
def getBranches = ("git ls-remote https://<username>:<password>@github.com/<org>/<repo>.git").execute()
def branchNameList = getBranches.text.readLines().collect {
it.split()[1]
}
def releaseBranchList = branchNameList.findAll { it =~ /refs\/heads\/release-candidate-20.*/ }
def humanReadableReleaseBranchList = releaseBranchList.collect {
it.replaceAll('refs/heads/', '')
}
return humanReadableReleaseBranchList
Я понимаю, что это не самый красивый вариант, я новичок в groovy.
Что я пробовал
Я, конечно, пробовал без <username>:<password>
, и это не сработало. Я также пробовал опцию секретный текст или файлы пользователя
в разделе Среда сборки
, чтобы попытаться получить переменные окружения учетных данных github. Но после долгих усилий с этим и чтения документации плагина параметров (active choice, extended choice и т.д.) стало очевидно, что они не имеют доступа к этим переменным окружения. Эти переменные, судя по всему, доступны только на этапе сборки. Если я не ошибаюсь. Я пробовал, чтобы убедиться, но был неуспешен. Вот пример того, как я пытался их получить.
- В разделе Среда сборки я выбрал “Секретный текст или файл пользователя”
- Назвал его и выбрал свои учетные данные github
- Затем в скрипте Groovy Active Parameter я сделал что-то вроде следующего (К вашему сведению: я пробовал несколько методов, не только этот. Если вы знаете другой способ, пожалуйста, дайте знать)
def envVars = Jenkins.instance.getGlobalNodeProperties()[0].getEnvVars()
def GITHUB_USER = envVars['GITHUB_USER']
def GITHUB_PASS = envVars['GITHUB_PASS']
def getBranches = ("git ls-remote https://GITHUB_USER:[email protected]/<org>/<repo>.git").execute()
Снова, я пробовал много способов. Возможно, мой синтаксис был неверным, опять же, я очень новичок в Groovy. Я пробовал что-то вроде def getBranches = ("git ls-remote https://" + GITHUB_USER + ":" + GITHUB_PASS + "@github.com/<org>/<repo>.git").execute()
и def getBranches = ("git ls-remote https://${GITHUB_USER}:${GITHUB_PASS}@github.com/<org>/<repo>.git").execute()
Почему я выбрал этот метод
Я знаю, что есть и другие подходы, такие как Jenkinsfile для конвейеров. Я изначально пытался это сделать, но не имел особого успеха, хотя я готов попробовать снова, если смогу преодолеть некоторые проблемы, которые не сработали для меня, такие как:
- Репозиторий
git ls-remote
отличается от репозитория, который будет содержать Jenkinsfile. Я мог бы, но не хочу помещать Jenkinsfile в репозиторий, над которым я пытаюсь выполнить git-операции, из-за необходимости проходить множество шагов QA, так как это код приложения. Я могу двигаться гораздо быстрее, если у меня будет Jenkinsfile в отдельном репозитории devops, отличном от кода приложения. - Добавление динамического параметра не всегда, казалось, обновляется
- Я также пробовал использовать API github, и по какой-то причине я получил разные результаты по веткам. Возможно, я смогу попробовать это снова и выяснить, почему, но я вложил много времени в это без успеха.
Я просто хотел проверить, есть ли, возможно, другое решение, которое я не нашел, прежде чем обращаться к подходу Jenkinsfile Pipeline Multirepo.
Я нашел решение, которое работало хорошо:
https://bart.jakubowski.in/jenkins-active-reactive-plugin/
В итоге у меня был такой код для получения и использования учетных данных (замените CREDENTIALS_ID на ваш ID в Jenkins):
import groovy.json.JsonSlurperClassic
import jenkins.model.Jenkins
creds = getCredentials()
def getCredentials() {
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
Jenkins.instance,
null,
null)
for (c in creds) {
if (c.id == "CREDENTIALS_ID") {
user = c.username
pass = c.password
}
}
def credentials = "${user}:${pass}"
return credentials.toString()
}
def command = [ "/bin/bash", "-c", "curl --user ${creds} https://some_site_which_requires_authentication" ]
Ответ или решение
Для реализации безопасного способа хранения и использования паролей в скрипте Groovy для Jenkins, можно воспользоваться системой управления учетными данными Jenkins. Ваш подход к получению веток из репозитория GitHub через параметры преднамеренно опасен, так как включает хранение пароля в открытом виде. Вместо этого, предлагается использовать безопасный способ доступа к учетным данным.
Шаги для реализации безопасной работы с учетными данными в Jenkins:
-
Создание учетных данных в Jenkins:
- Перейдите в раздел "Учетные данные" (Credentials) в Jenkins.
- Выберите подходящий домен или оставьте по умолчанию.
- Нажмите "Добавить учетные данные" (Add Credentials).
- Выберите тип "Username with password" и заполните поля с именем пользователя и паролем. Задайте уникальный идентификатор, который вы будете использовать в скрипте (например,
GITHUB_CREDENTIALS
).
-
Использование учетных данных в Groovy-скрипте:
- В вашем Groovy-скрипте используйте следующий код для безопасного получения учетных данных:
import jenkins.model.Jenkins
import com.cloudbees.plugins.credentials.CredentialsProvider
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials
def getCredentials(credentialsId) {
def creds = CredentialsProvider.lookupCredentials(StandardUsernameCredentials.class, Jenkins.instance, null, null)
for (credential in creds) {
if (credential.id == credentialsId) {
return [username: credential.username, password: credential.password]
}
}
return null // или выбросить исключение, если учетные данные не найдены
}
def credentials = getCredentials('GITHUB_CREDENTIALS')
if (credentials) {
def user = credentials.username
def pass = credentials.password
def getBranches = ("git ls-remote https://${user}:${pass}@github.com/<org>/<repo>.git").execute()
def branchNameList = getBranches.text.readLines().collect {
it.split()[1]
}
def releaseBranchList = branchNameList.findAll { it =~ /refs\/heads\/release-candidate-20.*/ }
def humanReadableReleaseBranchList = releaseBranchList.collect {
it.replaceAll('refs/heads/', '')
}
return humanReadableReleaseBranchList
} else {
error("Учетные данные не найдены")
}
Объяснение кода:
- getCredentials(credentialsId): Эта функция ищет учетные данные по указанному идентификатору и возвращает имя пользователя и пароль.
- Использование учетных данных: Внутри скрипта, после получения учетных данных, вы можете безопасно их использовать для выполнения команды
git ls-remote
.
Преимущества данного подхода:
- Безопасность: Учетные данные хранятся в Jenkins в зашифрованном виде, что предотвращает их утечку.
- Гибкость: Вы можете легко изменять учетные данные через интерфейс Jenkins, не редактируя скрипт.
- Чистота кода: Сокращение кода с паролями в открытом виде делает его более читаемым и менее подверженным ошибкам.
Заключение:
Использование учетных данных в Jenkins с помощью плагинов управления учетными данными — это оптимальный и безопасный способ работы с конфиденциальной информацией. Это не только улучшает безопасность вашего CI/CD процесса, но и упрощает управление учетными данными, что особенно важно при работе в командной среде.