JenkinsActiveChoice: различия между версиями
Материал из noname.com.ua
Перейти к навигацииПерейти к поискуSirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
Строка 7: | Строка 7: | ||
{{#spoiler:show=show version| |
{{#spoiler:show=show version| |
||
<PRE> |
<PRE> |
||
+ | import com.cloudbees.plugins.credentials.CredentialsProvider; |
||
− | cisco WS-C3560G-48PS (PowerPC405) processor (revision H0) with 131072K bytes of memory. |
||
+ | import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials; |
||
− | Switch Ports Model SW Version SW Image |
||
+ | import jenkins.model.Jenkins |
||
− | ------ ----- ----- ---------- ---------- |
||
+ | |||
− | * 1 52 WS-C3560G-48PS 12.2(55)SE12 C3560-IPBASEK9-M |
||
+ | |||
+ | // ВНИМАНИЕ - println пишет В ЛОГ и читать сообщение надо в логе дженкинса |
||
+ | // НА современных линуксах например: |
||
+ | // journalctl -u jenkins --since -1m -f |
||
+ | |||
+ | // Список приложений и их доступов |
||
+ | List reposAndKeys = [ |
||
+ | [ |
||
+ | "name": "app1", |
||
+ | "repo": "git@github.com:app1.git", |
||
+ | "repoKeyId": "app1-git-deployment-key", |
||
+ | ], |
||
+ | [ |
||
+ | "name": "app2", |
||
+ | "repo": "git@github.com:app2.git", |
||
+ | "repoKeyId": "appN-git-deployment-key", |
||
+ | ], |
||
+ | ... |
||
+ | [ |
||
+ | "name": "appN", |
||
+ | "repo": "git@github.com:appN.git", |
||
+ | "repoKeyId": "appN-git-deployment-key", |
||
+ | ] |
||
+ | ] |
||
+ | |||
+ | // Получение списка всех бранчей |
||
+ | def getAllBranches( String url, String credentialID, Boolean activeChoice = false, |
||
+ | String defaultBranch = 'master', Boolean includeTags = false, String logTag = "") { |
||
+ | def jenkinsCredentials = CredentialsProvider.lookupCredentials( |
||
+ | com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey, |
||
+ | Jenkins.instance |
||
+ | ); |
||
+ | def key = jenkinsCredentials.findResult { it.id == credentialID ? it.privateKey : null } |
||
+ | |||
+ | if (!key) { |
||
+ | return "[${logTag}]Error: credentials not found" |
||
+ | } else { |
||
+ | print("[${logTag}] Key Found: \n ${key} \n") |
||
+ | } |
||
+ | |||
+ | // иногда с первого раза не удается получить все бранчи |
||
+ | Integer attemptsLeft = 5 |
||
+ | def out = new StringBuilder() |
||
+ | def err = new StringBuilder() |
||
+ | |||
+ | while(attemptsLeft > 0) { |
||
+ | try { |
||
+ | print("[${logTag}] Starting process\n") |
||
+ | Process process = ['ssh-agent', 'bash', '-c', "echo '" + key + "' | ssh-add - 2> /dev/null && git ls-remote -t -h " + url].execute() |
||
+ | process.consumeProcessOutput(out, err) |
||
+ | print("[${logTag}] Waiting for started process\n") |
||
+ | process.waitFor() |
||
+ | print("[${logTag}] Process is finished\n") |
||
+ | print("[${logTag}] Out: \n${out}\n\n") |
||
+ | if (out == null) { |
||
+ | attemptsLeft = attemptsLeft - 1 |
||
+ | print("[${logTag}] Output ${out} is null. attemptsLeft = ${attemptsLeft} \n") |
||
+ | continue |
||
+ | } |
||
+ | if (out.size() == 0) { |
||
+ | attemptsLeft = attemptsLeft - 1 |
||
+ | print("[${logTag}] Output ${out} is empty. attemptsLeft = ${attemptsLeft} \n") |
||
+ | continue |
||
+ | } |
||
+ | print("[${logTag}] Out: ${out} looks OK\n") |
||
+ | break |
||
+ | } catch(Exception Ex) { |
||
+ | println("[${logTag}] " + Ex.toString()) |
||
+ | throw new Exception(Ex) |
||
+ | } |
||
+ | } // while |
||
+ | |||
+ | if (err.size() > 0) { |
||
+ | return err |
||
+ | } |
||
+ | |||
+ | if (out.size() > 0) { |
||
+ | def branches = out.readLines().collect { |
||
+ | it.split()[1] |
||
+ | }.findAll { |
||
+ | it.startsWith('refs/heads/') || includeTags |
||
+ | }.collect { |
||
+ | it.replaceAll('refs/heads/', '').replaceAll('refs/tags/', '') |
||
+ | } |
||
+ | if (activeChoice) { |
||
+ | def defaultBranchIndex = branches.indexOf(defaultBranch) |
||
+ | if (defaultBranchIndex >= 0) { |
||
+ | branches.set(defaultBranchIndex, defaultBranch + ':selected') |
||
+ | } |
||
+ | } |
||
+ | println("Branches found: ${branches}") |
||
+ | return branches |
||
+ | } |
||
+ | } |
||
+ | |||
+ | List applications = [] |
||
+ | List branches = [] |
||
+ | // Просто список приложений - только имена |
||
+ | reposAndKeys.each { repoAndKey -> |
||
+ | applications.add(repoAndKey["name"]) |
||
+ | } |
||
+ | println("applications = ${applications}") |
||
+ | |||
+ | //Флаг который нужен что бы определить когда |
||
+ | // чекбокс снят |
||
+ | Boolean isDisabled = false |
||
+ | |||
+ | List triggeredByParameterNames = [] |
||
+ | // Параметр который триггерит вызов этого скрипта должен называться так же как одно |
||
+ | // из имен приложений |
||
+ | |||
+ | // Логика тут примерно такая |
||
+ | // - есть несколько параметров приложений, например app1, app2, app3 ... appN |
||
+ | // - есть массив конфигураций с конфигурацией для каждого приложение - ИМЯ, адрес, ключ .. |
||
+ | // - ИМЯ приложения в этом массиве ДОЛЖНО совпадать с именем переменной которая является Referenced parameters |
||
+ | // Другими словами имя параментра (например app1) должно совпадать с именем ("name": "app1") в массиве конйигураций |
||
+ | // При старте скрипта в нем создается переменная которая указана в Referenced parameters с таким же именем |
||
+ | // т.е. всегда будет доступна одна из переменных - app1 ИЛИ app2 ИЛИ ... ИЛИ appN но проблема |
||
+ | // в том что в коде заранее не известно имя этой переменной (так как код скрипта полностью одинаков и делать |
||
+ | // несколько копий скрипта, каждая для своего приложения, не хочется) |
||
+ | // |
||
+ | // Код ниже пытается определить какая из переменных определена, для этого он последовательно пробует прочитать значения |
||
+ | // всех возможных и в случае успеха - запоминает какая переменная доступна |
||
+ | // Есди переменная доступна но ее значение - пуста строка то это значит что чекбокс снят и нужно выдать пустой список |
||
+ | // Если переменная доступна и ее значение не равно пустой строке - то это значит что чекбокс выбран и нужно получить список |
||
+ | // бранчей |
||
+ | // (Пустрая строка или что-то другое - зависит от ТИПА переменной и этот код не универсален) |
||
+ | applications.each { it -> |
||
+ | try { |
||
+ | // если it указывает на несуществующее значенеи то тут будет исключение |
||
+ | println("${it} = ${this[ it ]}") |
||
+ | |||
+ | // Если чекбокс не выбран - то в значении переменной (имя переменной это имя параметра) будет пустая строка |
||
+ | // тут нужно добаить другие проверки если планируется использовать другиме типы параметов |
||
+ | if ("${this[ it ]}" == "") { |
||
+ | isDisabled = true |
||
+ | } |
||
+ | triggeredByParameterNames.add("${it}") |
||
+ | } catch(Exception Ex) { |
||
+ | println("${it}") |
||
+ | println(Ex) |
||
+ | } |
||
+ | } |
||
+ | |||
+ | print("triggeredByParameterNames = ${triggeredByParameterNames}\n") |
||
+ | print("triggeredByParameterNames size = ${triggeredByParameterNames.size()}\n") |
||
+ | |||
+ | if (isDisabled) { |
||
+ | print("Application is not selected for deploy\n") |
||
+ | return [] |
||
+ | } |
||
+ | |||
+ | // В какой-то момент времени происходит выхов и НИ одна переменная не оказывается доступна - что бы не ловить исключения |
||
+ | // аозвращаю пустой List |
||
+ | if (triggeredByParameterNames.size == 0 ) { |
||
+ | print("No valid applivation found (Possible reason: script misconfiguration or started without required parameters)\n") |
||
+ | return [] |
||
+ | } |
||
+ | |||
+ | |||
+ | |||
+ | // Проверить что вызвано только одним приложением |
||
+ | // Это означает что для каждого приложения должен быть свой параметр имени ветки |
||
+ | // и нельзя сделать так что бы пересчет этого параметра триггерился 2 или более |
||
+ | // параметрами (так как это в целом не имеет смысла) |
||
+ | if (triggeredByParameterNames.size > 1 ) { |
||
+ | return ["Triggered by multiple parameters is not supported, please check Referenced parameters setting, only one parameter is allowed "] |
||
+ | } |
||
+ | String logTag = triggeredByParameterNames[0].toString() |
||
+ | |||
+ | repoAndKey = reposAndKeys.findAll { it.name == triggeredByParameterNames[0] } |
||
+ | print("[${logTag}] Parameters are: ${repoAndKey}\n") |
||
+ | String credentialsId = repoAndKey[0]['repoKeyId'] |
||
+ | String url = repoAndKey[0]['repo'] |
||
+ | |||
+ | |||
+ | |||
+ | // Собственно вызов получения списка бранчей |
||
+ | getAllBranches(url, credentialsId, true, "master", false, logTag) |
||
</PRE> |
</PRE> |
||
}} |
}} |
Версия 10:43, 12 июля 2022
Jenkins Active Choice
Есть плагин который позволяет динамически формировать значения параметров, например динамически подтягивать список веток в git (НО нельзя динамически создать параметры, и у меня не вышло сделать скрытыми параметры в зависимости от того что выбрано в другом параметре)