feat(api-tools): native TS tools for Jira/Confluence/GitLab, drop MCP bridge
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
---
|
||||
name: confluence
|
||||
description: Используй, когда нужно найти или написать документацию в корпоративном Confluence — поискать страницы, прочитать содержимое, создать новую страницу. Применяй при вопросах «где документация», «есть ли дока по», «помогить найти в вики», «создай страницу», а также в команде /rfc.
|
||||
---
|
||||
|
||||
# Работа с документацией (Confluence)
|
||||
|
||||
Скилл покрывает поиск и создание страниц в корпоративной вики. Адрес и токен берутся
|
||||
автоматически — ничего не хардкодь и не спрашивай.
|
||||
|
||||
## Откуда адрес и токен
|
||||
|
||||
- **Адрес** — из `docsUrl` в `config/company.json` (в контекст сессии его инжектит
|
||||
расширение `company-context`). Можно переопределить переменной `CONFLUENCE_URL`.
|
||||
- **Токен** — `CONFLUENCE_TOKEN` (personal access token). Задаётся в
|
||||
`~/.config/pi-kit/env.sh`. Не подставляй его в команды и не логируй.
|
||||
|
||||
## Инструменты
|
||||
|
||||
Доступны как нативные инструменты pi (регистрирует `extensions/confluence-tools.ts`):
|
||||
|
||||
- **`confluence_search`** — поиск страниц по CQL-запросу.
|
||||
Примеры CQL:
|
||||
- `text = "деплой"` — по тексту;
|
||||
- `title = "RFC"` — по заголовку;
|
||||
- `space = TECHRUN AND type = page` — в конкретном пространстве;
|
||||
- сложное: `(text = "kubernetes" OR title = "k8s") AND space = SRE`.
|
||||
- **`confluence_page_get`** — получить страницу по ID (с `expandBody` — вернуть текст).
|
||||
- **`confluence_page_create`** — создать страницу в пространстве (body — HTML в Storage
|
||||
format или обычный текст; укажи `parentId` для вложенности).
|
||||
|
||||
## Соглашения
|
||||
|
||||
- **Сначала ищи, потом создавай.** Прежде чем писать новую страницу — `confluence_search`
|
||||
по теме, чтобы не дублировать существующую.
|
||||
- **Храни адреса страниц** в ответах — верни URL созданной/найденной страницы пользователю.
|
||||
- Если инструмент вернул ошибку «проверь токен» — попроси пользователя проверить
|
||||
`CONFLUENCE_TOKEN`, не выдавай сам токен.
|
||||
- Ключи пространств (`spaceKey`) — реальные значения посмотри через `confluence_search`; если
|
||||
запросили создать страницу, а пространство неизвестно — уточни у пользователя.
|
||||
|
||||
## Полезное
|
||||
|
||||
- Для RFC/ADR часто нужен свежий поиск в пространстве архитектуры — используй
|
||||
`confluence_search` с `space =` нужного пространства. Если карта документации
|
||||
(`docs-map`) ещё с TODO — не выдумывай пространства, спроси пользователя или начни с
|
||||
поиска, чтобы определить реальные.
|
||||
@@ -1,71 +1,52 @@
|
||||
---
|
||||
name: jira-workflow
|
||||
description: Используй, когда нужно работать с корпоративным трекером задач (Jira) — прочитать тикет по ключу, добавить комментарий, приложить ссылку на MR, разобраться в статусах и переходах. Применяй при упоминании ключей задач, «тикет», «задача в трекере», «переведи в статус», а также в командах /bugfix и /feature.
|
||||
description: Используй, когда нужно работать с корпоративным трекером задач (Jira) — прочитать тикет по ключу, создать/обновить задачу, добавить комментарий, перевести по статусам, найти по JQL, приложить ссылку на MR. Применяй при упоминании ключей задач, «тикет», «задача в трекере», «переведи в статус», а также в командах /bugfix и /feature.
|
||||
---
|
||||
|
||||
# Работа с трекером задач (Jira)
|
||||
|
||||
Скилл описывает, как читать и обновлять задачи в нашем трекере через REST API.
|
||||
Jira работает через **нативные инструменты pi** (регистрируют `extensions/jira-tools.ts`).
|
||||
Никаких bash-скриптов и MCP — вызывай инструменты напрямую.
|
||||
|
||||
## Откуда берутся адрес и токен
|
||||
## Откуда адрес и токен
|
||||
|
||||
**Никогда не хардкодь и не спрашивай их отдельно — они уже есть в окружении.**
|
||||
- **Адрес трекера** — из `trackerUrl` в `config/company.json` (в контекст сессии инжектит
|
||||
`company-context`). Можно переопределить `TRACKER_URL`.
|
||||
- **Токен** — `JIRA_TOKEN` (personal access token) из `~/.config/pi-kit/env.sh`.
|
||||
- Токен не подставляй в команды и не логируй — инструменты читают его сами.
|
||||
|
||||
- **Базовый адрес трекера** — из переменной окружения `TRACKER_URL`. Если она не задана,
|
||||
возьми адрес трекера из корпоративного контекста сессии (его инжектит расширение
|
||||
`company-context`).
|
||||
- **Токен доступа** — из переменной окружения `JIRA_TOKEN` (personal access token).
|
||||
- Токен в команды и логи не подставляй в открытом виде — скрипты читают его из окружения сами.
|
||||
## Инструменты
|
||||
|
||||
Для создания merge request в GitLab дополнительно нужен `GITLAB_TOKEN` (токен с scope `api`);
|
||||
хост и путь проекта скрипт определяет из `git remote origin` (или `GITLAB_HOST`) — адреса не хардкодятся.
|
||||
- **`jira_issue_get(key)`** — получить тикет (summary, status, description).
|
||||
- **`jira_issue_create(projectKey, summary, issuetype, ...)`** — создать задачу.
|
||||
- **`jira_issue_update(key, {summary?, description?, status?, ...})`** — обновить поля,
|
||||
`status` переводит по доступным переходам.
|
||||
- **`jira_issue_comment(key, text)`** — добавить комментарий.
|
||||
- **`jira_issue_transition(key, target)`** — перевести в статус
|
||||
(`To Do` / `In Progress` / `Review` / `Done`, поддерживаются русские синонимы).
|
||||
- **`jira_search(jql, maxResults?)`** — поиск по JQL.
|
||||
- **`jira_link_mr(key, mrUrl, title?)`** — привязать ссылку на MR (комментарием).
|
||||
|
||||
Быстрая проверка окружения:
|
||||
## Типовой поток багфикса (/bugfix)
|
||||
|
||||
```bash
|
||||
: "${TRACKER_URL:?установи TRACKER_URL или возьми адрес из корпоративного контекста}"
|
||||
: "${JIRA_TOKEN:?установи JIRA_TOKEN (personal access token трекера)}"
|
||||
```
|
||||
|
||||
## Готовые скрипты
|
||||
|
||||
Все скрипты лежат в `scripts/` и читают `TRACKER_URL` и `JIRA_TOKEN` из окружения:
|
||||
|
||||
- `./scripts/get-issue.sh <KEY>` — получить тикет (поля summary, status, description).
|
||||
- `./scripts/add-comment.sh <KEY> "<текст>"` — добавить комментарий.
|
||||
- `./scripts/link-mr.sh <KEY> "<url-MR>" ["<заголовок>"]` — приложить ссылку на MR
|
||||
(добавляется комментарием со ссылкой; при доступном remote link API — см. TODO в скрипте).
|
||||
- `./scripts/create-mr.sh "<title>" [target] [source] [jira-key]` — создать merge request в
|
||||
GitLab (по текущей ветке), вывести его URL и, если передан `jira-key` и заданы
|
||||
`TRACKER_URL`/`JIRA_TOKEN`, автоматически приложить ссылку к тикету.
|
||||
|
||||
Пример:
|
||||
|
||||
```bash
|
||||
./scripts/get-issue.sh PROJ-123
|
||||
./scripts/add-comment.sh PROJ-123 "Начал работу, воспроизвёл баг"
|
||||
./scripts/link-mr.sh PROJ-123 "https://<git-host>/ai/foo/-/merge_requests/42" "Fix PROJ-123"
|
||||
|
||||
# создать MR из текущей ветки в main и сразу привязать к тикету:
|
||||
GITLAB_TOKEN=... ./scripts/create-mr.sh "Fix PROJ-123: NPE" main "" PROJ-123
|
||||
```
|
||||
|
||||
Флаги окружения `create-mr.sh`: `GITLAB_TOKEN` (обязателен), `GITLAB_HOST` (override хоста),
|
||||
`MR_PUSH=0` (не пушить ветку), `MR_DRY_RUN=1` (показать запрос без вызова API).
|
||||
MR из защищённой/релизной ветки (`main`/`master`/`release-*`) скрипт создавать откажется.
|
||||
1. `jira_issue_get <KEY>` — прочитать постановку.
|
||||
2. `jira_issue_transition <KEY> "In Progress"` — при старте работы.
|
||||
3. Создать ветку/фикс (языковые стандарты — в профильном скилле).
|
||||
4. Перед мержем — `gitlab_mr_create` (см. скилл gitlab) и
|
||||
`jira_link_mr <KEY> <url-MR>` — привязать MR к тикету.
|
||||
5. `jira_issue_transition <KEY> "Review"` — после выставления MR.
|
||||
6. `jira_issue_transition <KEY> "Done"` — после мержа.
|
||||
|
||||
## Соглашения
|
||||
|
||||
- **Формат ключей задач:** вида `PROJ-123` (буквенный префикс проекта + номер).
|
||||
`<!-- TODO: перечислить реальные префиксы проектов -->`
|
||||
- **Статусы и переходы:** To Do → In Progress → Review → Done.
|
||||
- **Кто и когда меняет статус:** разработчик переводит тикет: в **In Progress** — при старте работы;
|
||||
в **Review** — при выставлении MR (в тикет добавляется ссылка на MR); в **Done** — после мержа.
|
||||
- **Что писать в комментарии:** при старте — кратко о начале работы; при готовности — ссылку на MR
|
||||
(используй `create-mr.sh`, который сразу приложит ссылку, либо `link-mr.sh`).
|
||||
- **Формат ключей:** `PROJ-123` (префикс проекта + номер).
|
||||
- **Статусы:** To Do → In Progress → Review → Done.
|
||||
- **Переходы:** при старте — In Progress; при готовности MR — Review (с ссылкой на MR);
|
||||
после мержа — Done.
|
||||
- Если `jira_issue_update` со `status` не смог найти переход — инструмент вернёт список
|
||||
доступных статусов; уточни нужный.
|
||||
|
||||
## Полезное
|
||||
|
||||
- ID переходов статуса можно получить через `GET /rest/api/2/issue/<KEY>/transitions`,
|
||||
выполнить переход — `POST` туда же с `{"transition":{"id":"<id>"}}`.
|
||||
- Если API возвращает 401/403 — проверь `JIRA_TOKEN` и права. Не логируй сам токен.
|
||||
- `jira_search` удобен для «что в работе у меня»: `jira_search('assignee = currentUser() AND status != Done')`.
|
||||
- Токен лежит в `~/.config/pi-kit/env.sh` (chmod 600).
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# add-comment.sh <ISSUE_KEY> "<comment text>"
|
||||
# Adds a comment to a tracker issue.
|
||||
# Reads TRACKER_URL and JIRA_TOKEN from the environment. No secrets are hardcoded.
|
||||
set -euo pipefail
|
||||
|
||||
KEY="${1:?usage: add-comment.sh <ISSUE_KEY> \"<text>\"}"
|
||||
TEXT="${2:?usage: add-comment.sh <ISSUE_KEY> \"<text>\"}"
|
||||
: "${TRACKER_URL:?set TRACKER_URL (or take the tracker address from the session corporate context)}"
|
||||
: "${JIRA_TOKEN:?set JIRA_TOKEN (tracker personal access token)}"
|
||||
|
||||
BASE="${TRACKER_URL%/}"
|
||||
|
||||
# Build JSON body safely (jq escapes the text); fall back to a naive body if jq is absent.
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
BODY="$(jq -n --arg b "$TEXT" '{body: $b}')"
|
||||
else
|
||||
BODY="{\"body\": \"${TEXT//\"/\\\"}\"}"
|
||||
fi
|
||||
|
||||
curl -fsS -X POST \
|
||||
-H "Authorization: Bearer ${JIRA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$BODY" \
|
||||
"${BASE}/rest/api/2/issue/${KEY}/comment" >/dev/null
|
||||
|
||||
echo "Comment added to ${KEY}"
|
||||
@@ -1,112 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# create-mr.sh "<title>" [target-branch] [source-branch] [jira-key]
|
||||
#
|
||||
# Creates a GitLab merge request for the current repository via the GitLab API.
|
||||
# Host and project path are derived from `git remote origin` (or GITLAB_HOST),
|
||||
# so no URLs are hardcoded. If a Jira key is given and TRACKER_URL/JIRA_TOKEN are
|
||||
# set, the MR link is also attached to the ticket via link-mr.sh.
|
||||
#
|
||||
# Env:
|
||||
# GITLAB_TOKEN (required) GitLab personal/project access token with api scope
|
||||
# GITLAB_HOST (optional) override host, e.g. git.codelab.vc
|
||||
# MR_PUSH (optional) 0 to skip pushing the source branch (default: push)
|
||||
# MR_DRY_RUN (optional) 1 to print the request and exit without calling the API
|
||||
#
|
||||
# Examples:
|
||||
# ./create-mr.sh "Fix PROJ-123: null pointer" main
|
||||
# ./create-mr.sh "Add feature X" main feature/PROJ-42-x PROJ-42
|
||||
set -euo pipefail
|
||||
|
||||
TITLE="${1:?usage: create-mr.sh \"<title>\" [target-branch] [source-branch] [jira-key]}"
|
||||
TARGET="${2:-main}"
|
||||
SOURCE="${3:-$(git rev-parse --abbrev-ref HEAD)}"
|
||||
JIRA_KEY="${4:-}"
|
||||
|
||||
: "${GITLAB_TOKEN:?set GITLAB_TOKEN (GitLab access token with api scope)}"
|
||||
|
||||
# --- Refuse to open an MR *from* a protected branch (safety). ----------------
|
||||
case "$SOURCE" in
|
||||
main | master | release-* | release/*)
|
||||
echo "Refusing: source branch '$SOURCE' looks protected/release. Create a feature branch first." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Derive host and project path from the origin remote. -------------------
|
||||
URL="$(git config --get remote.origin.url)"
|
||||
URL="${URL%.git}"
|
||||
case "$URL" in
|
||||
*://*) # scheme://[user@]host[:port]/path
|
||||
REST="${URL#*://}"
|
||||
REST="${REST#*@}"
|
||||
HOST_PORT="${REST%%/*}"
|
||||
PATH_NS="${REST#*/}"
|
||||
HOST="${HOST_PORT%%:*}"
|
||||
;;
|
||||
*@*:*) # scp-like: user@host:path
|
||||
REST="${URL#*@}"
|
||||
HOST="${REST%%:*}"
|
||||
PATH_NS="${REST#*:}"
|
||||
;;
|
||||
*)
|
||||
echo "Cannot parse origin remote URL: $URL" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
HOST="${GITLAB_HOST:-$HOST}"
|
||||
if [ -z "$HOST" ] || [ -z "$PATH_NS" ]; then
|
||||
echo "Could not determine GitLab host/project from origin ($URL). Set GITLAB_HOST." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# URL-encode the project path (only '/' needs encoding for a namespaced path).
|
||||
PROJECT_ENC="${PATH_NS//\//%2F}"
|
||||
API="https://${HOST}/api/v4/projects/${PROJECT_ENC}/merge_requests"
|
||||
|
||||
# --- Build request body (jq escapes; fall back to naive JSON). --------------
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
BODY="$(jq -n \
|
||||
--arg s "$SOURCE" --arg t "$TARGET" --arg title "$TITLE" \
|
||||
'{source_branch:$s, target_branch:$t, title:$title, remove_source_branch:true, squash:true}')"
|
||||
else
|
||||
BODY="{\"source_branch\":\"${SOURCE}\",\"target_branch\":\"${TARGET}\",\"title\":\"${TITLE//\"/\\\"}\",\"remove_source_branch\":true,\"squash\":true}"
|
||||
fi
|
||||
|
||||
if [ "${MR_DRY_RUN:-0}" = "1" ]; then
|
||||
echo "DRY RUN"
|
||||
echo "POST ${API}"
|
||||
echo "body: ${BODY}"
|
||||
echo "would push: $([ "${MR_PUSH:-1}" = "1" ] && echo "git push -u origin ${SOURCE}" || echo "(skipped)")"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Ensure the source branch exists on the remote. -------------------------
|
||||
if [ "${MR_PUSH:-1}" = "1" ]; then
|
||||
git push -u origin "$SOURCE"
|
||||
fi
|
||||
|
||||
# --- Create the MR. ---------------------------------------------------------
|
||||
RESPONSE="$(curl -fsS -X POST \
|
||||
-H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$BODY" "$API")"
|
||||
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
WEB_URL="$(printf '%s' "$RESPONSE" | jq -r '.web_url // empty')"
|
||||
else
|
||||
WEB_URL="$(printf '%s' "$RESPONSE" | sed -n 's/.*"web_url":"\([^"]*\)".*/\1/p' | head -1)"
|
||||
fi
|
||||
|
||||
if [ -z "$WEB_URL" ]; then
|
||||
echo "MR request sent, but could not parse web_url from response:" >&2
|
||||
echo "$RESPONSE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "MR created: $WEB_URL"
|
||||
|
||||
# --- Optionally attach the MR link to the Jira ticket. ----------------------
|
||||
if [ -n "$JIRA_KEY" ] && [ -n "${TRACKER_URL:-}" ] && [ -n "${JIRA_TOKEN:-}" ]; then
|
||||
"$(dirname "$0")/link-mr.sh" "$JIRA_KEY" "$WEB_URL" "$TITLE"
|
||||
fi
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# get-issue.sh <ISSUE_KEY>
|
||||
# Prints summary, status and description of a tracker issue.
|
||||
# Reads TRACKER_URL and JIRA_TOKEN from the environment. No secrets are hardcoded.
|
||||
set -euo pipefail
|
||||
|
||||
KEY="${1:?usage: get-issue.sh <ISSUE_KEY>}"
|
||||
: "${TRACKER_URL:?set TRACKER_URL (or take the tracker address from the session corporate context)}"
|
||||
: "${JIRA_TOKEN:?set JIRA_TOKEN (tracker personal access token)}"
|
||||
|
||||
BASE="${TRACKER_URL%/}"
|
||||
|
||||
curl -fsS \
|
||||
-H "Authorization: Bearer ${JIRA_TOKEN}" \
|
||||
-H "Accept: application/json" \
|
||||
"${BASE}/rest/api/2/issue/${KEY}?fields=summary,status,description" \
|
||||
| { jq -r '"\(.key)\t\(.fields.status.name)\n\(.fields.summary)\n\n\(.fields.description // "")"' 2>/dev/null || cat; }
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# link-mr.sh <ISSUE_KEY> "<mr-url>" ["<title>"]
|
||||
# Attaches a merge request link to a tracker issue.
|
||||
# Default implementation posts a comment with the link (works on any Jira).
|
||||
# Reads TRACKER_URL and JIRA_TOKEN from the environment. No secrets are hardcoded.
|
||||
set -euo pipefail
|
||||
|
||||
KEY="${1:?usage: link-mr.sh <ISSUE_KEY> \"<mr-url>\" [\"<title>\"]}"
|
||||
URL="${2:?usage: link-mr.sh <ISSUE_KEY> \"<mr-url>\" [\"<title>\"]}"
|
||||
TITLE="${3:-Merge request}"
|
||||
: "${TRACKER_URL:?set TRACKER_URL (or take the tracker address from the session corporate context)}"
|
||||
: "${JIRA_TOKEN:?set JIRA_TOKEN (tracker personal access token)}"
|
||||
|
||||
BASE="${TRACKER_URL%/}"
|
||||
|
||||
# Default: comment with the MR link.
|
||||
COMMENT="${TITLE}: ${URL}"
|
||||
exec "$(dirname "$0")/add-comment.sh" "$KEY" "$COMMENT"
|
||||
|
||||
# TODO: если в компании используется remote issue link API, заменить на:
|
||||
# POST ${BASE}/rest/api/2/issue/${KEY}/remotelink
|
||||
# с телом {"object":{"url":"<URL>","title":"<TITLE>"}}
|
||||
Reference in New Issue
Block a user