Intro
Благородя своей гибкости, Jira в большинстве крупных компаний, используется в качестве единой системы принятия решений и отслеживания изменений.
Вопреки расхожему мнению, далеко не все компании занимаются разработкой софта.
Во многих крупных организациях Dev и Ops – это всего лишь одно структурное подразделение, так называемый Cost Center (то есть напрямую компании доходы не приносит). При этом одной из главных задач в Agile является обеспечение прозрачности процессов для всех заинтересованных сторон (stakeholders).
Для многих компаний парадигма JiraOps или скорее IssueTrackingOps подходит гораздо лучше, чем GitOps.
Для того, чтобы убрать препоны между бизнесом, DEV, OPS, SEC, QA и обеспечить прозрачность процессов можно разрабатывать свою автоматизацию для Jira, либо использовать инструменты от сторонних разработчиков.
Jira Server
Для работы нам понадобится Jira Data Center – тестовый стенд с триальной версией Jira.
Для этих целей будем использовать docker-compose.yml:
version: '3.7' services: node: image: atlassian/jira-software:latest ports: - 9099:8080 volumes: - ./jira-home-node1:/var/atlassian/application-data/jira:Z ulimits: nproc: 65535 nofile: soft: 65535 hard: 65535 database: image: postgres:10.5-alpine volumes: - ./postgresql-data:/var/lib/postgresql/data:Z - ./postgre-db-init.sql:/docker-entrypoint-initdb.d/postgre-db-init.sql:Z ports: - 5432:5432 environment: POSTGRES_PASSWORD: 1234
Запускаем Jira Server:
docker-compose up -d
Jira UI будет доступен по адресу http://<IP_ADDRESS>:9099
Нужно будет прокликать установочный визард, сгенерировать триальный ключ и создать пользователя.
CLI
У Jira есть отличный API и клиентские библиотеки для Python и Jira.
Для автоматизации CI/CD и мониторинга мы будем использовать go-jira (https://github.com/go-jira/jira), а для BI и ad-hoc аналитики Python и SQL.
Go-jira это и библиотека для работы с API Jira и инструмент командной строки, который идеально подходит для встраивания в CI/CD процессы.
Пример использования Go-клиента – получаем jira issues для проекта OpenJDK:
main.go:
package main import ( "fmt" "github.com/andygrunwald/go-jira" ) func main() { jiraClient, _ := jira.NewClient(nil, "https://bugs.openjdk.org") jql := "project = JDK and status = Open ORDER BY updated ASC" issues, resp, err := jiraClient.Issue.Search(jql, nil) if err != nil { fmt.Println(err) panic(resp.StatusCode) } for _, issue := range issues { fmt.Printf("%s: %+v\n", issue.Key, issue.Fields.Summary) } }
Получаем issues для проекта OpenJDK:
go run main.go | head -10 JDK-4158929: 8 bit Dithering problem in SwingSet HTML Text tab. JDK-4184200: Color profiles for screen device should be used when available. JDK-4199882: splotchy highlight at 24 bit True Color JDK-4345973: Add set/get methods for boolean datatype in ParameterBlock JDK-4148927: Input method highlighting needs to handle highlight segments JDK-4102920: 12x: Multi-font caching scheme inadequate for non-Latin text JDK-4387892: swing components show all black @ 16-bit depth (VNC on Linux) JDK-4398379: java.awt.image.DataBufferShort constructor should verify size of array JDK-4398381: java.awt.image.DataBufferShort should check for negative size JDK-4396157: Merlin: Consonant RA Rule R2 doesn't hold true with Lucida font
Благородя CLI с Jira можно работать так же как и Git:
jira mine +--------+------------+-------+----------+--------+----------+--------------+--------------+ | Issue | Summary | Type | Priority | Status | Age | Reporter | Assignee | +--------+------------+-------+----------+--------+----------+--------------+--------------+ | JIRA-1 | Jira-1 | Story | Medium | To Do | an hour | Anton Krylov | Anton Krylov | | JIRA-2 | Demo Issue | Bug | Medium | To Do | a minute | Anton Krylov | Anton Krylov | +--------+------------+-------+----------+--------+----------+--------------+--------------+
Только сначала нужно будет создать конфиг для Jira:
mkdir ~/.jira.d cat <<EOM >~/.jira.d/config.yml endpoint: https://jira.mycompany.com EOM
config.yml
config: stop: true password-source: stdin endpoint: http://<IP>:9099 user: <user> login: <login> project: JIRA queries: todo: >- resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'To Do' custom-commands: - name: env help: print the JIRA environment variables available to custom commands script: |- env | sort | grep JIRA - name: print-project help: print the name of the configured project script: "echo $JIRA_PROJECT" - name: jira-path help: print the path the jira command that is running this alias script: |- echo {{jira}} - name: mine help: display issues assigned to me script: |- {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND assignee=currentuser() ORDER BY status, issue" - name: mine-created help: display issues created by me script: |- {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND creator=currentuser() ORDER BY created" - name: watching help: display issues watched by me script: |- {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND watcher=currentuser() ORDER BY created" script: |- if [ -n "$JIRA_PROJECT" ]; then # if `project: ...` configured just list the issues for current project {{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() and project = $JIRA_PROJECT ORDER BY priority asc, created" else # otherwise list issues for all project {{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() ORDER BY priority asc, created" fi - name: sprint help: display issues for active sprint script: |- if [ -n "$JIRA_PROJECT" ]; then # if `project: ...` configured just list the issues for current project {{jira}} list --template table --query "sprint in openSprints() and type != epic and resolution = unresolved and project=$JIRA_PROJECT ORDER BY rank asc, created" else # otherwise list issues for all project {{jira}} list --template table --query "sprint in openSprints() and type != epic and resolution = unresolved ORDER BY rank asc, created" fi
Если в кофиге password-source: stdin то пароль для jira нужно передавать следующим образом:
export JIRA_PASSWORD='<PASSWORD>\n' echo $JIRA_PASSWORD| jira ls
Если будет password-source: pass то jira «попросит» его в интерактивном режиме.
jira mine это custom-command который выводит все jira issues для текущего пользователя.
Таким образом можно создавать различные команды использующие api и jql для работы с jira.
- name: mine help: display issues assigned to me script: |- {{jira}} list --template table --query "resolution = unresolved AND project=$JIRA_PROJECT AND assignee=currentuser() ORDER BY status, issue"
Можно быстро прикреплять файлы к issues из Bash:
jira attach create JIRA-1 exec.zip OK 10000 http://109.207.172.67:9099/secure/attachment/10000/exec.zip
А если их несколько то можно написать Bash-скрипт:
for i in exec1.zip exec2.zip exec3.zip exec4.zip; do jira attach create JIRA-1 $i; done OK 10003 http://109.207.172.67:9099/secure/attachment/10003/exec1.zip OK 10004 http://109.207.172.67:9099/secure/attachment/10004/exec2.zip OK 10005 http://109.207.172.67:9099/secure/attachment/10005/exec3.zip OK 10006 http://109.207.172.67:9099/secure/attachment/10006/exec4.zip
Вложения можно быстро скачивать из командной строки:
jira attach list JIRA-1 +-------+-----------+---------+--------------+-----------+ | id | filename | bytes | user | created | +-------+-----------+---------+--------------+-----------+ | 10000 | exec.zip | 4209783 | Anton Krylov | 5 minutes | | 10001 | exec.zip | 4209783 | Anton Krylov | 3 minutes | | 10002 | exec.zip | 4209783 | Anton Krylov | 3 minutes | | 10003 | exec1.zip | 4209783 | Anton Krylov | a minute | | 10004 | exec2.zip | 4209783 | Anton Krylov | a minute | | 10005 | exec3.zip | 4209783 | Anton Krylov | a minute | | 10006 | exec4.zip | 4209783 | Anton Krylov | a minute | +---
Представьте себе, что вам нужно выполнять какие-то однокипные действия – например генерировать сертификаты для нового кластера Kubernetes.
Вы написали скрипт, который делает это автоматически:
make -f mkcerts.mk root-ca generating root-key.pem generating root-cert.csr generating root-cert.pem Certificate request self-signature ok subject=O=Istio, CN=Root CA
А теперь эту задачу должен проконтролировать ИБ:
jira attach create JIRA-1 kube_certs.tar OK 10007 http://109.207.172.67:9099/secure/attachment/10007/kube_certs.tar
Представим себе, что нужно создать SSH-ключ для нового сотрудника. И конечно эта задача должны пройти несколько стадий проверки, а в случаи если сотрудник покидает компанию, вся информацию об этой задачи и ключах будет хранится в Jira:
Эту задачу можно превратить в YAML-шаблон, параметризовать и хранить в Git:
Задача может быть и посложней – например генерировать сертификаты для кластера Kafka:
bash genkeys.sh
Эти файлы нужно заархивировать:
tree . ├── broker-ca-signed.crt ├── broker.csr ├── broker_keystore_creds ├── broker_sslkey_creds ├── broker_truststore_creds ├── consumer-ca-signed.crt ├── consumer.csr ├── consumer_keystore_creds ├── consumer_sslkey_creds ├── consumer_truststore_creds ├── genkeys.sh ├── jcerts-kafka-ca-key.pem ├── jcerts-kafka-ca.pem ├── jcerts-kafka-ca.srl ├── kafka.broker.keystore.cer.pem ├── kafka.broker.keystore.jks ├── kafka.broker.keystore.key.pem ├── kafka.broker.keystore.p12 ├── kafka.broker.truststore.jks ├── kafka.consumer.keystore.cer.pem ├── kafka.consumer.keystore.jks ├── kafka.consumer.keystore.key.pem ├── kafka.consumer.keystore.p12 ├── kafka.consumer.truststore.jks ├── kafka.producer.keystore.cer.pem ├── kafka.producer.keystore.jks ├── kafka.producer.keystore.key.pem ├── kafka.producer.keystore.p12 ├── kafka.producer.truststore.jks ├── producer-ca-signed.crt ├── producer.csr ├── producer_keystore_creds ├── producer_sslkey_creds └── producer_truststore_creds
И прикрепить к задаче:
find . -print0 | tar -cvf kafka_certs.tar --null -T - jira attach create JIRA-2 kafka_certs.tar OK 10100 http://109.207.172.67:9099/secure/attachment/10100/kafka_certs.tar
Автоматизация может быть и сложнее, поэтому неплохо было-бы это все «завернуть» в Docker, положить в Git и добавить в CI:
Dockerfile:
ARG JIRA_PROJECT ENV JIRA_PASSWORD=JIRA_PROJECT RUN apt-get update && apt-get -y install golang RUN go install github.com/go-jira/jira/cmd/jira@latest RUN ln -s ~/go/bin/jira /usr/local/bin/jira COPY config.yml ~/.jira.d/config.yml COPY gencerts.sh gencerts.sh RUN bash gencerts.sh RUN jira attach create INFRA kafka_certs.tar
положить в Git и сделать частью CI:
docker build . --build-arg='JIRA_PROJECT=INFRA'
GUI
Существует несколько GUI клиентов для Jira.
Один из них давно перешел в статус «Deprecated», но без проблем работает с последними версиями Jira:
Для чего это нужно?
-
Бывает множество нетехнических пользователей, которым сложно привыкнуть к Web-UI Jira.
-
Иногда в закрытом контуре, в принципе нет доступа к браузеру, на рабочем месте.
End
PS. Если наберется 50 лайков, то я напишу вторую, часть, где мы разберем как прикрутить продвинутый BI для Jira, без лишних хлопот и скриптов на Groovy.
ссылка на оригинал статьи https://habr.com/ru/articles/786444/
Добавить комментарий