@lilflexer/task-flow-cli
v1.4.1
Published
Global GitHub and ClickUp task workflow CLI
Readme
task-flow
Самостоятельный глобальный Node.js/TypeScript CLI для GitHub/ClickUp workflow.
Пакет не требует файлов, зависимостей или конфигурации в репозиториях
frontend, backend, admin и может запускаться из любой вложенной директории
Git-репозитория.
Установка
Требования: Node.js 18+, Git и авторизованный
GitHub CLI (gh).
npm install
npm run build
npm linkПосле npm link доступны полная команда и короткие aliases:
task-flow --help
tf --help
tfc --help
tfs --help
tfsub --helpЧтобы удалить link, выполните
npm unlink -g @lilflexer/task-flow-cli.
Конфигурация
Создайте глобальный файл ~/.config/task-flow/config.json:
{
"defaults": {
"branch": "master",
"pullRequestBranches": {
"master": "master",
"staging": "staging"
},
"branchPrefix": "feat",
"remote": "origin",
"pull": true,
"draft": false,
"clickup": {
"branchFieldId": "clickup-branch-custom-field-id",
"productionPullRequestFieldId": "clickup-production-pr-custom-field-id",
"stagingPullRequestFieldId": "clickup-staging-pr-custom-field-id",
"deployFlowFieldName": "Deploy Flow"
}
},
"repositories": {
"company/frontend": {
"branch": "master",
"pullRequestBranches": {
"master": "master",
"staging": "staging"
},
"tasks": {
"remove-bottom-blur": "86cb1ewr4"
}
},
"company/backend": {
"pullRequestBranches": {
"master": "main",
"staging": "develop"
},
"branchPrefix": "feature",
"clickup": {
"branchFieldId": "backend-branch-field-id"
}
}
}
}Поддерживаемые свойства слоя defaults и каждого repository override:
branch— базовая ветка (masterпо умолчанию);pullRequestBranches.master— основной target PR; если не задан, используется итоговое значениеbranch;pullRequestBranches.staging— target PR дляDeploy Flow = Staging;branchPrefix— префикс рабочей ветки (featпо умолчанию);featureBranch— необязательное полное имя рабочей ветки;remote— Git remote (originпо умолчанию);pull— выполнятьgit pull --ff-onlyперед созданием ветки;draft— создавать draft PR;clickup.apiBaseUrl—https://api.clickup.com/api/v2по умолчанию;clickup.branchFieldId— ID текстового custom field для веток;clickup.productionPullRequestFieldId— ID текстового custom field для PR в production;clickup.stagingPullRequestFieldId— ID текстового custom field для PR в staging;clickup.deployFlowFieldName— имя custom field с режимом deploy (Deploy Flowпо умолчанию);clickup.deployFlowFieldId— необязательный ID поля Deploy Flow; если задан, имеет приоритет над поиском по имени;clickup.teamId— требуется только при использовании custom task IDs.
Каждый repository override также может содержать tasks — автоматически
поддерживаемое соответствие полного имени feature-ветки и ClickUp task ID:
{
"tasks": {
"remove-bottom-blur": "86cb1ewr4",
"feat/86cavbfx9": "86cavbfx9"
}
}Одна ветка не может быть связана с разными задачами. При конфликте CLI завершается с ошибкой и не перезаписывает существующий task ID.
Итоговое значение выбирается в порядке:
CLI argument
→ repositories["owner/repository"]
→ defaults
→ встроенные значенияТокен ClickUp задаётся через окружение:
export CLICKUP_API_TOKEN=pk_...или через ~/.config/task-flow/.env:
CLICKUP_API_TOKEN=pk_...Переменная процесса имеет приоритет над .env. Рекомендуется ограничить права
на файл: chmod 600 ~/.config/task-flow/.env.
Использование
Создать feat/86cavbfx9 от master и записать ветку в ClickUp:
cd ~/project/frontend/packages/some-package
task-flow start 86cavbfx9 --branch=masterПередать полное пользовательское имя ветки можно вторым аргументом:
task-flow start 86cb1ewr4 remove-bottom-blur
tfs 86cb1ewr4 remove-bottom-blurПосле успешного start CLI сохраняет полученную ветку и task ID в
repositories["owner/repository"].tasks глобального config.
Опубликовать текущую ветку, найти её task ID в config, прочитать Deploy Flow,
найти или создать PR и записать URL в ClickUp:
task-flow submit
tfsubМожно явно передать имя любой сохранённой ветки:
task-flow submit remove-bottom-blur
tfsub remove-bottom-blurЕсли эта ветка не является текущей, CLI проверяет её наличие в remote,
не выполняет git push и открывает PR с этой remote-веткой в качестве head.
Для обратной совместимости аргумент без соответствующей записи в tasks
считается task ID и связывается с текущей веткой после успешного submit:
task-flow submit 86cb1ewr4
tfsub 86cb1ewr4Commit с названием задачи
Создать commit с названием связанной ClickUp-задачи:
task-flow commit
tfcCLI находит task ID текущей ветки в repository tasks, получает название
задачи, выполняет из корня репозитория:
git add .
git commit -m "<ClickUp task name>"Чтобы commit-ить только уже staged изменения, не выполняя git add .:
tfc --stagedGit commit hooks можно пропустить стандартной короткой или полной опцией:
tfc -n
tfc --no-verify
tfc --staged --no-verifyПри создании PR его body всегда начинается с названия и URL задачи ClickUp.
Дополнительное описание передаётся через --description:
task-flow submit \
86cavbfx9 \
--description="Implemented API validation and updated tests"Результат в описании каждого создаваемого PR:
Add some stuff - https://app.clickup.com/t/86cavbfx9
Implemented API validation and updated testsЕсли --description не передан, body содержит только строку с задачей ClickUp.
Все параметры конфигурации можно переопределить в CLI:
task-flow start \
86cavbfx9 \
--branch=main \
--pr-master-branch=main \
--pr-staging-branch=staging \
--branch-prefix=fix \
--no-pull \
--branch-field-id=custom-field-id
task-flow submit \
86cavbfx9 \
--description="Implementation details" \
--pr-master-branch=master \
--pr-staging-branch=staging \
--draft \
--production-pull-request-field-id=production-custom-field-id \
--staging-pull-request-field-id=staging-custom-field-id \
--deploy-flow-field-id=deploy-flow-field-idПолный список параметров: task-flow --help.
Полные и короткие формы эквивалентны:
| Полная форма | Короткая форма |
| --- | --- |
| task-flow | tf |
| task-flow commit | tfc |
| task-flow start TASK_ID [BRANCH] | tfs TASK_ID [BRANCH] |
| task-flow submit [BRANCH_OR_TASK_ID] | tfsub [BRANCH_OR_TASK_ID] |
Deploy Flow и target-ветки PR
Команда submit читает custom field Deploy Flow из связанной задачи ClickUp.
Поддерживаются два значения:
| Deploy Flow | Создаваемые PR |
| --- | --- |
| Staging | сначала pullRequestBranches.staging, после merge — promotion в pullRequestBranches.master |
| Production | только pullRequestBranches.master |
Для dropdown-поля CLI преобразует сохранённый ClickUp option ID или
orderindex в отображаемое значение Staging/Production. Текстовые значения
также поддерживаются. Пустое, неизвестное значение или отсутствующая
pullRequestBranches.staging для Staging Flow приводят к понятной ошибке до
публикации ветки.
Promotion после staging
Менять Deploy Flow после тестирования не требуется. При повторном submit
для Deploy Flow = Staging CLI проверяет PR из feature-ветки в настроенную
staging-ветку:
- если PR отсутствует, он создаётся;
- если PR открыт, CLI использует существующий URL и не создаёт дубликат;
- если PR смержен, CLI проверяет, что commit выбранной feature-ветки совпадает с последним протестированным commit этого PR;
- если master PR уже открыт или смержен, используется его существующий URL;
- иначе CLI предлагает promotion:
PR to staging_release is already merged.
Press Enter to open PR to master_release or q to cancel:Enter создаёт PR в pullRequestBranches.master. q или Q завершает
команду с сообщением Cancelled без git fetch, git push и обновления
ClickUp. Для prompt требуется интерактивный терминал.
Если после merge staging PR в feature-ветке появились новые коммиты, promotion
блокируется: эти изменения должны сначала пройти новый staging PR и
тестирование. Для promotion ветки pullRequestBranches.master и
pullRequestBranches.staging должны отличаться.
Перед публикацией feature-ветки CLI fetch-ит настроенные target-ветки в
remote-tracking refs. Это позволяет gh pr create --fill корректно вычислять
title/body, даже если target-ветка ещё не была fetched в локальном репозитории.
Объекты pullRequestBranches объединяются по обычному приоритету
CLI → repository → defaults. Например, repository override может изменить
только staging, сохранив master из defaults.
Как определяется репозиторий
Сначала CLI выполняет из текущей директории:
git rev-parse --show-toplevelТак находится настоящий repository root даже при запуске из вложенной
директории. Все последующие команды git и gh запускаются с cwd, равным
этому root.
Затем CLI получает nameWithOwner:
gh repo view --json nameWithOwner --jq .nameWithOwnerЕсли это невозможно, используется:
git remote get-url originПоддерживаются HTTPS, SSH URL и SCP-подобный формат
[email protected]:owner/repository.git. Имя локальной директории не используется
как идентификатор репозитория. Вне Git-репозитория CLI завершается с понятной
ошибкой.
Значения ClickUp
Custom fields должны быть текстовыми. CLI хранит одну строку на репозиторий:
company/frontend: feat/86cavbfx9
company/backend: feat/86cavbfx9Production и staging pull requests записываются в отдельные custom fields,
настроенные через productionPullRequestFieldId и
stagingPullRequestFieldId. В каждом поле сохраняется название репозитория и
ссылка на соответствующий PR:
company/frontend: https://github.com/company/frontend/pull/124
company/backend: https://github.com/company/backend/pull/44Повторный запуск обновляет только строку текущего owner/repository; строки и
прочие непустые данные других репозиториев сохраняются.
