From 3adf0c5211d8f9e1c8662c5e4719fbc7b70c1d20 Mon Sep 17 00:00:00 2001 From: PTah Date: Thu, 18 Jun 2026 09:51:39 +1000 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20Cursor=20rules,=20init-cursor=20=D0=B8=20=D1=81=D0=BA?= =?UTF-8?q?=D1=80=D0=B8=D0=BF=D1=82=D1=8B=20=D0=BD=D0=B0=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B9=D0=BA=D0=B8=20git=20remotes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Канонический источник для клонирования в $HOME\CursorRules на новых ПК. --- .cursor/rules/00-always-read-rules.mdc | 28 ++++++ .cursor/rules/01-context-control.mdc | 24 +++++ .cursor/rules/agent-monitors-version-bump.mdc | 18 ++++ .cursor/rules/csharp-spec.mdc | 12 +++ .cursor/rules/gitea-home-api.mdc | 37 +++++++ .cursor/rules/no-cursor-in-repositories.mdc | 50 ++++++++++ .cursor/rules/powershell-spec.mdc | 12 +++ .cursor/rules/python-spec.mdc | 12 +++ .cursor/rules/version-bump-rdp.mdc | 20 ++++ .cursor/rules/version-bump-ssh.mdc | 18 ++++ .cursor/rules/version-bump.mdc | 14 +++ .cursorignore | 65 +++++++++++++ .gitignore | 2 + README.md | 25 ++++- init-cursor.ps1 | 92 ++++++++++++++++++ local/papatramp-gitea.conf.example | 11 +++ scripts/Ensure-GiteaHomeRepo.ps1 | 63 ++++++++++++ scripts/Set-GitRemotes.ps1 | 97 +++++++++++++++++++ 18 files changed, 599 insertions(+), 1 deletion(-) create mode 100644 .cursor/rules/00-always-read-rules.mdc create mode 100644 .cursor/rules/01-context-control.mdc create mode 100644 .cursor/rules/agent-monitors-version-bump.mdc create mode 100644 .cursor/rules/csharp-spec.mdc create mode 100644 .cursor/rules/gitea-home-api.mdc create mode 100644 .cursor/rules/no-cursor-in-repositories.mdc create mode 100644 .cursor/rules/powershell-spec.mdc create mode 100644 .cursor/rules/python-spec.mdc create mode 100644 .cursor/rules/version-bump-rdp.mdc create mode 100644 .cursor/rules/version-bump-ssh.mdc create mode 100644 .cursor/rules/version-bump.mdc create mode 100644 .cursorignore create mode 100644 .gitignore create mode 100644 init-cursor.ps1 create mode 100644 local/papatramp-gitea.conf.example create mode 100644 scripts/Ensure-GiteaHomeRepo.ps1 create mode 100644 scripts/Set-GitRemotes.ps1 diff --git a/.cursor/rules/00-always-read-rules.mdc b/.cursor/rules/00-always-read-rules.mdc new file mode 100644 index 0000000..35460ae --- /dev/null +++ b/.cursor/rules/00-always-read-rules.mdc @@ -0,0 +1,28 @@ +--- +description: Перед работой — прочитай все применимые rules +alwaysApply: true +--- + +# Всегда читай правила + +Перед **любой** задачей (код, git, push, релиз, ответ пользователю): + +1. **Прочитай все применимые rules** — user rules, workspace `.cursor/rules/`, особенно с `alwaysApply: true`. +2. **Не начинай работу**, пока не понял ограничения из rules (git, Cursor в репо, version-bump, язык ответа и т.д.). +3. **При конфликте** запроса пользователя и rule — остановись, объясни конфликт, спроси подтверждение. + +## Обязательные проверки по типу задачи + +| Задача | Перед действием прочитай / проверь | +|--------|-------------------------------------| +| `git commit` / `push` | `no-cursor-in-repositories` — нет `.cursor/` в staged; `.gitignore` содержит `.cursor/` | +| Push в `home` | `gitea-home-api` — сначала API, потом SSH push | +| Bump версии | `version-bump` (+ `version-bump-rdp` / `version-bump-ssh` для агентских мониторов) | +| Коммит | `git log -1 --format=fuller` — нет `cursoragent`, `Co-authored-by: Cursor` | + +## Если rule нарушен + +- **Не push**, не «доделывай быстрее». +- Исправь (amend / filter / commit-tree), затем снова проверь лог. + +Правила важнее скорости выполнения задачи. \ No newline at end of file diff --git a/.cursor/rules/01-context-control.mdc b/.cursor/rules/01-context-control.mdc new file mode 100644 index 0000000..99c71af --- /dev/null +++ b/.cursor/rules/01-context-control.mdc @@ -0,0 +1,24 @@ +--- +description: Git, контекст файлов и формат ответов +alwaysApply: true +--- + +# Контекст и дисциплина + +## Git + +- **Не** `git commit` / **не** `git push` без явной команды пользователя. +- Перед commit: покажи `git diff --stat`, дождись подтверждения. +- Conventional Commits: `feat:`, `fix:`, `docs:`, `refactor:`. + +## Контекст + +- Файлы: `@`, открытые вкладки, явные пути — не сканируй весь репо без запроса. +- Не грузи файлы >500 строк без необходимости. +- Локальные копии; не качай пакеты/URL без ошибки сборки или явного запроса. + +## Ответы + +- Язык: **русский** (если пользователь не переключился). +- По коду — diff/фрагменты, не дублируй неизменённые блоки. +- Без воды, но достаточно полно для понимания (не обрезай сложные ответы до одной строки). diff --git a/.cursor/rules/agent-monitors-version-bump.mdc b/.cursor/rules/agent-monitors-version-bump.mdc new file mode 100644 index 0000000..e392354 --- /dev/null +++ b/.cursor/rules/agent-monitors-version-bump.mdc @@ -0,0 +1,18 @@ +--- +description: Bump версии RDP/SSH агентов — иначе ПК не обновятся +globs: **/Login_Monitor.ps1,**/Deploy-LoginMonitor.ps1,**/Sac-Client.ps1,**/ssh-monitor,**/sac-client.sh,**/update_ssh_monitor.sh +alwaysApply: false +--- + +# Версии агентских мониторов + +Любая **существенная правка** без bump **не доедет** до компьютеров. + +| Стек | Файлы | Поле / файл версии | +|------|-------|-------------------| +| RDP | `Login_Monitor.ps1`, `version.txt` | `$ScriptVersion` = `version.txt` | +| SSH | `ssh-monitor`, `version.txt` | `SSH_MONITOR_VERSION` = `version.txt` | + +Подробности: `version-bump-rdp.mdc`, `version-bump-ssh.mdc`. + +**SAC backend:** `backend/app/version.py` (`APP_VERSION`) — отдельный релиз, на агенты ПК не влияет. diff --git a/.cursor/rules/csharp-spec.mdc b/.cursor/rules/csharp-spec.mdc new file mode 100644 index 0000000..3bb4116 --- /dev/null +++ b/.cursor/rules/csharp-spec.mdc @@ -0,0 +1,12 @@ +--- +description: Краткий C# без лишних токенов в выводе +globs: **/*.cs +alwaysApply: false +--- + +# C# — компактный вывод + +- File-scoped namespaces, pattern matching, target-typed `new()`, primary constructors где уместно. +- Без XML-комментариев, `#region`, лишних `using`. +- Без `Console.WriteLine` / debug-log, если задача не про логирование. +- Expression-bodied members, где читаемо. diff --git a/.cursor/rules/gitea-home-api.mdc b/.cursor/rules/gitea-home-api.mdc new file mode 100644 index 0000000..a1de0c9 --- /dev/null +++ b/.cursor/rules/gitea-home-api.mdc @@ -0,0 +1,37 @@ +--- +description: Gitea home — репо через API, не вручную в вебе +alwaysApply: true +--- + +# Gitea home (papatramp) + +При push в **`home`**, настройке remotes или первом заливе — **через Gitea API**. Не проси создать репо вручную при `Push to create is not enabled` / `Cannot find repository`. + +## Пути (локально, не в git-репо) + +| Назначение | Путь | +|------------|------| +| Конфиг API (секреты) | `$HOME\CursorRules\local\papatramp-gitea.conf` | +| Remotes | `$HOME\CursorRules\scripts\Set-GitRemotes.ps1` | +| Создать репо на home | `$HOME\CursorRules\scripts\Ensure-GiteaHomeRepo.ps1` | + +`init-cursor` копирует в репо **только `*.mdc`**. + +SSH **`home`**: `ssh://git@git.papatramp.lan:2222/PapaTramp/.git` + +## Алгоритм + +1. `GET {GiteaApiUrl}/api/v1/repos/PapaTramp/{RepoName}` — Basic Auth из конфига. +2. Если **404** — `POST {GiteaApiUrl}/api/v1/user/repos` (или `.../orgs/PapaTramp/repos`), тело: `{ "name": "", "private": true, "auto_init": false }`. + Или: `Ensure-GiteaHomeRepo.ps1 -RepoName `. +3. `git push home ` (SSH). + +## Запрещено + +- «Создайте репо в Gitea сами» без попытки API. +- Коммитить `papatramp-gitea.conf`, пароли, временные скрипты с credentials. +- HTTPS/`origin` для home вместо remote **`home`**. + +## API недоступен + +Сообщи, что LAN/API (`192.168.128.48:3000`) недоступен — VPN/сеть. Не отправляй в веб-интерфейс. diff --git a/.cursor/rules/no-cursor-in-repositories.mdc b/.cursor/rules/no-cursor-in-repositories.mdc new file mode 100644 index 0000000..59c9f04 --- /dev/null +++ b/.cursor/rules/no-cursor-in-repositories.mdc @@ -0,0 +1,50 @@ +--- +description: Не коммитить .cursor/ и IDE-файлы в git-репозитории +alwaysApply: true +--- + +# Cursor не попадает в git + +В **коммитах и tracked-файлах** запрещено добавлять артефакты Cursor как IDE/агента. + +## Запрещено коммитить + +| Путь | Назначение | +|------|------------| +| **`.cursor/`** | rules, hooks, hooks.json, settings — только локально | +| **`.cursorignore`** | индексация IDE, не часть продукта | +| **`AGENTS.md`**, **`CURSOR.md`** | служебные файлы IDE | + +Не создавать `.cursor/hooks/` с auto-push/auto-commit в репозиториях проекта. + +## Обязательно в `.gitignore` каждого репо + +```gitignore +.cursor/ +.cursorignore +``` + +При работе в репозитории: если строк нет — **добавить в том же коммите**, что и код, **не** коммитить сами `.cursor/`. + +После `init-cursor` (копирование rules в проект) — rules остаются **локально** и **не попадают** в `git add`. + +## Перед `git commit` / `git push` + +1. `git status` — в staged **нет** `.cursor/` и `.cursorignore`. +2. **Не** использовать `git add -A` / `git add .` без проверки. +3. Если `.cursor` уже в индексе: `git rm -r --cached .cursor` и `git rm --cached .cursorignore`. +4. `git ls-files` — не должно быть путей, начинающихся с `.cursor`. + +## Запрещено в тексте коммитов и docs + +- Упоминания Cursor IDE, Cursor Agent, cursoragent, cursor.com, cursor.sh. +- Trailers: Co-authored-by: Cursor, Made-with: Cursor. + +## Разрешено (не путать с IDE) + +- CSS cursor: pointer; poll cursor, DB cursor, Console.CursorLeft, MOEX analytics.cursor. + +## Git / GitHub + +- Author и committer — Andrey Lutsenko, без co-author Cursor. +- Перед push в public: git log --format=fuller, поиск cursoragent / Co-authored-by: Cursor. diff --git a/.cursor/rules/powershell-spec.mdc b/.cursor/rules/powershell-spec.mdc new file mode 100644 index 0000000..588777f --- /dev/null +++ b/.cursor/rules/powershell-spec.mdc @@ -0,0 +1,12 @@ +--- +description: Компактный PowerShell в выводе агента +globs: **/*.{ps1,psm1} +alwaysApply: false +--- + +# PowerShell — компактный вывод + +- Pipeline вместо многострочных `foreach`, где читаемо. +- Без comment-based help и лишних `Write-Host`, если не просили UI/логи. +- Не дублируй длинные CLI-аргументы целиком — placeholder или переменная. +- Сохраняй стиль и алиасы **существующего файла**; не навязывай `gc`/`gci` если в проекте полные имена. diff --git a/.cursor/rules/python-spec.mdc b/.cursor/rules/python-spec.mdc new file mode 100644 index 0000000..4d3b5cf --- /dev/null +++ b/.cursor/rules/python-spec.mdc @@ -0,0 +1,12 @@ +--- +description: Компактный Python в выводе агента +globs: **/*.py +alwaysApply: false +--- + +# Python — компактный вывод + +- Comprehensions, ternary — где читаемо; stdlib (`pathlib`, `json`, `subprocess`) без лишних зависимостей. +- Type hints — только если уже приняты в файле. +- Без docstrings/комментариев «для объяснения», если не просили. +- При правках — функция/метод, не весь файл; `# ... existing code ...` для неизменных блоков. diff --git a/.cursor/rules/version-bump-rdp.mdc b/.cursor/rules/version-bump-rdp.mdc new file mode 100644 index 0000000..0fc7375 --- /dev/null +++ b/.cursor/rules/version-bump-rdp.mdc @@ -0,0 +1,20 @@ +--- +description: Bump version.txt и $ScriptVersion в RDP-login-monitor +globs: **/Login_Monitor.ps1,**/Deploy-LoginMonitor.ps1,**/Sac-Client.ps1,**/Exchange-MailSecurity.ps1,**/Watchdog_RDP_Monitor.ps1,**/version.txt +alwaysApply: false +--- + +# Bump RDP-login-monitor + +Без bump **`Deploy-LoginMonitor.ps1` не обновит ПК** (`version.txt` vs `deployed_version.txt`). + +## В том же коммите + +1. `Login_Monitor.ps1` — `$ScriptVersion` (напр. `2.0.7-SAC`) +2. `version.txt` — **та же строка** + +Patch: `2.0.6-SAC` → `2.0.7-SAC`. Крупный релиз — minor по смыслу. + +`Exchange-MailSecurity.ps1` — свой `$ScriptVersion`, bump только при правке этого пакета. + +После bump — публикация на NETLOGON. diff --git a/.cursor/rules/version-bump-ssh.mdc b/.cursor/rules/version-bump-ssh.mdc new file mode 100644 index 0000000..6aa4de3 --- /dev/null +++ b/.cursor/rules/version-bump-ssh.mdc @@ -0,0 +1,18 @@ +--- +description: Bump version.txt и SSH_MONITOR_VERSION в ssh-monitor +globs: **/ssh-monitor,**/sac-client.sh,**/update_ssh_monitor.sh,**/version.txt +alwaysApply: false +--- + +# Bump ssh-monitor + +Без bump **`update_ssh_monitor.sh` не скопирует скрипт** (sha256). + +## В том же коммите + +1. `ssh-monitor` — `SSH_MONITOR_VERSION="X.Y.Z-SAC"` +2. `version.txt` — **та же строка** + +Patch по умолчанию. `sac-client.sh` версию не задаёт — берёт из установленного `ssh-monitor`. + +После push: `git pull` + `update_ssh_monitor.sh` на хостах. diff --git a/.cursor/rules/version-bump.mdc b/.cursor/rules/version-bump.mdc new file mode 100644 index 0000000..c7aeb4a --- /dev/null +++ b/.cursor/rules/version-bump.mdc @@ -0,0 +1,14 @@ +--- +description: Patch/minor bump версии при осмысленных правках +alwaysApply: true +--- + +# Bump версии + +## Patch (обычно) + +После осмысленного изменения — **+0.0.1** (`0.7.0` → `0.7.1`) в **том же коммите**. + +## Minor / major + +При заметном релизе — по смыслу (`0.6.x` → `0.7.0`). Не обязательно на каждую мелочь. diff --git a/.cursorignore b/.cursorignore new file mode 100644 index 0000000..f5740f9 --- /dev/null +++ b/.cursorignore @@ -0,0 +1,65 @@ +# +node_modules/ +bower_components/ +jspm_packages/ +.npm/ +vendor/ +.pnpm-store/ + +# (Python) +.venv/ +venv/ +env/ +ENV/ +.env/ + +# , +dist/ +build/ +out/ +.next/ +.nuxt/ +.docusaurus/ +.cache/ +.sass-cache/ +.turbo/ +target/ +bin/ +obj/ + +# IDE +.git/ +.svn/ +.idea/ +.vscode/ +.cursor/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# , +*.png +*.jpg +*.jpeg +*.gif +*.svg +*.ico +*.mp4 +*.mp3 +*.pdf +*.zip +*.tar.gz +*.rar +*.exe +*.dll +*.woff +*.woff2 +*.ttf +*.eot + +# (, ) +package-lock.json +yarn.lock +pnpm-lock.yaml +poetry.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca2d565 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Локальные секреты (не коммитить) +local/papatramp-gitea.conf diff --git a/README.md b/README.md index 8ceda60..84b06e4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,26 @@ # Rules -Правила для развертывания связи между новым компьютером и репозиториями \ No newline at end of file +Правила и скрипты для настройки нового компьютера: Cursor rules, git remotes, home Gitea. + +## Первичная настройка + +```powershell +git clone https://git.kalinamall.ru/PapaTramp/Rules $HOME\CursorRules +Copy-Item $HOME\CursorRules\local\papatramp-gitea.conf.example $HOME\CursorRules\local\papatramp-gitea.conf +# Заполнить GiteaApiPassword в local\papatramp-gitea.conf +``` + +Добавьте `init-cursor` в профиль PowerShell (один раз): + +```powershell +. $HOME\CursorRules\init-cursor.ps1 +``` + +## В каждом проекте + +```powershell +cd C:\path\to\repo +init-cursor +``` + +Скрипт копирует `.cursorignore` и `.cursor/rules/*.mdc`, при необходимости дополняет `.gitignore`, настраивает remotes (`home`, `github`, `kalinamall`) и создаёт репозиторий на home Gitea через API. diff --git a/init-cursor.ps1 b/init-cursor.ps1 new file mode 100644 index 0000000..9b4da44 --- /dev/null +++ b/init-cursor.ps1 @@ -0,0 +1,92 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + Копирует Cursor rules в текущий каталог и настраивает git remotes. + +.DESCRIPTION + 1. .cursorignore из $HOME\CursorRules + 2. .cursor/rules/*.mdc + 3. В git-репо: Set-GitRemotes.ps1 + Ensure-GiteaHomeRepo.ps1 (home Gitea) + +.EXAMPLE + cd C:\Users\papat\Projects\MyRepo + init-cursor +#> +function init-cursor { + [CmdletBinding()] + param( + [switch]$SkipGitRemotes + ) + + $source = Join-Path $HOME 'CursorRules' + $rulesSrc = Join-Path $source '.cursor\rules' + $scripts = Join-Path $source 'scripts' + + if (-not (Test-Path $source)) { + Write-Host "Error: $source not found" -ForegroundColor Red + return + } + + $cursorIgnore = Join-Path $source '.cursorignore' + if (Test-Path $cursorIgnore) { + Copy-Item $cursorIgnore . -Force + Write-Host '[+] .cursorignore copied' -ForegroundColor Green + } + + if (Test-Path $rulesSrc) { + New-Item -ItemType Directory -Path '.\.cursor\rules' -Force | Out-Null + Copy-Item (Join-Path $rulesSrc '*.mdc') '.\.cursor\rules\' -Force + Write-Host '[+] .cursor/rules (*.mdc) copied' -ForegroundColor Green + } + + $gitIgnorePath = Join-Path (Get-Location) '.gitignore' + $ignoreLines = @('.cursor/', '.cursorignore') + if (Test-Path (Join-Path (Get-Location) '.git')) { + if (-not (Test-Path $gitIgnorePath)) { + Set-Content -Path $gitIgnorePath -Value ($ignoreLines -join "`n") -Encoding UTF8 + Write-Host '[+] .gitignore created (.cursor/, .cursorignore)' -ForegroundColor Green + } + else { + $existing = Get-Content $gitIgnorePath -Raw + $added = @() + foreach ($line in $ignoreLines) { + if ($existing -notmatch "(?m)^$([regex]::Escape($line))\s*$") { + Add-Content -Path $gitIgnorePath -Value $line + $added += $line + } + } + if ($added.Count -gt 0) { + Write-Host "[+] .gitignore updated: $($added -join ', ')" -ForegroundColor Green + } + } + } + + if ($SkipGitRemotes) { + Write-Host '[!] Git remotes skipped (-SkipGitRemotes)' -ForegroundColor Yellow + return + } + + git rev-parse --is-inside-work-tree 2>$null | Out-Null + if ($LASTEXITCODE -ne 0) { + Write-Host '[!] Not a git repo — remotes skipped' -ForegroundColor Yellow + return + } + + $setRemotes = Join-Path $scripts 'Set-GitRemotes.ps1' + if (Test-Path $setRemotes) { + Write-Host '[*] Configuring git remotes...' -ForegroundColor Cyan + & powershell -NoProfile -ExecutionPolicy Bypass -File $setRemotes + } + + $ensureRepo = Join-Path $scripts 'Ensure-GiteaHomeRepo.ps1' + if (Test-Path $ensureRepo) { + $repoName = Split-Path -Leaf (git rev-parse --show-toplevel) + Write-Host "[*] Ensuring home Gitea repo: $repoName" -ForegroundColor Cyan + try { + & powershell -NoProfile -ExecutionPolicy Bypass -File $ensureRepo -RepoName $repoName + } + catch { + Write-Host "[!] home Gitea ensure failed: $($_.Exception.Message)" -ForegroundColor Yellow + } + } +} diff --git a/local/papatramp-gitea.conf.example b/local/papatramp-gitea.conf.example new file mode 100644 index 0000000..960a1e0 --- /dev/null +++ b/local/papatramp-gitea.conf.example @@ -0,0 +1,11 @@ +Type=gitea +GiteaHost=git.papatramp.ru +GiteaPort=2222 +GiteaWebUrl=https://git.papatramp.ru +GiteaApiUrl=http://192.168.128.48:3000 +GiteaApiUser=papatramp +GiteaApiPassword= +HostAlias=git.papatramp.ru +KeyName=id_ed25519_git_papatramp +KeyComment=papatramp@papatramp.ru +ExtraHosts=git.papatramp.lan|192.168.128.48|2222,git.papatramp-haproxy|192.168.128.65|2222 diff --git a/scripts/Ensure-GiteaHomeRepo.ps1 b/scripts/Ensure-GiteaHomeRepo.ps1 new file mode 100644 index 0000000..939321e --- /dev/null +++ b/scripts/Ensure-GiteaHomeRepo.ps1 @@ -0,0 +1,63 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + Создать репозиторий на home Gitea через API, если его ещё нет. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)][string]$RepoName, + [string]$Owner = 'PapaTramp', + [string]$ConfigPath = "$HOME\CursorRules\local\papatramp-gitea.conf", + [string]$Description = '' +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $ConfigPath)) { + throw "Config not found: $ConfigPath" +} + +$cfg = @{} +Get-Content -LiteralPath $ConfigPath | ForEach-Object { + if ($_ -match '^([^#=]+)=(.*)$') { + $cfg[$Matches[1].Trim()] = $Matches[2].Trim() + } +} + +$base = $cfg.GiteaApiUrl.TrimEnd('/') +$pair = '{0}:{1}' -f $cfg.GiteaApiUser, $cfg.GiteaApiPassword +$auth = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair)) +$headers = @{ Authorization = $auth; 'Content-Type' = 'application/json' } + +$checkUrl = "$base/api/v1/repos/$Owner/$RepoName" +try { + $existing = Invoke-RestMethod -Method Get -Uri $checkUrl -Headers $headers -TimeoutSec 15 + Write-Host "[+] EXISTS $($existing.full_name)" -ForegroundColor Green + exit 0 +} +catch { + if ($_.Exception.Response.StatusCode.value__ -ne 404) { + throw "check failed: $($_.Exception.Message)" + } +} + +$body = (@{ + name = $RepoName + private = $true + auto_init = $false + description = $Description +} | ConvertTo-Json) + +foreach ($url in @("$base/api/v1/orgs/$Owner/repos", "$base/api/v1/user/repos")) { + try { + $created = Invoke-RestMethod -Method Post -Uri $url -Headers $headers -Body $body -TimeoutSec 30 + Write-Host "[+] CREATED $($created.full_name)" -ForegroundColor Green + exit 0 + } + catch { + Write-Warning "create via $url : $($_.Exception.Message)" + } +} + +throw 'failed to create repository on home Gitea' diff --git a/scripts/Set-GitRemotes.ps1 b/scripts/Set-GitRemotes.ps1 new file mode 100644 index 0000000..c21fc2b --- /dev/null +++ b/scripts/Set-GitRemotes.ps1 @@ -0,0 +1,97 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + Стандартные git remote: home, kalinamall, github. + +.EXAMPLE + cd C:\Users\papat\Projects\MyRepo + & "$HOME\CursorRules\scripts\Set-GitRemotes.ps1" +#> +[CmdletBinding()] +param( + [string]$Owner = 'PapaTramp', + [string]$GithubOrg = 'PTah', + [string]$Repo = '', + [switch]$SkipKalinamall, + [switch]$WhatIf +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +function Write-Step([string]$Message) { Write-Host "[*] $Message" -ForegroundColor Cyan } +function Write-Ok([string]$Message) { Write-Host "[+] $Message" -ForegroundColor Green } + +function Test-GitRepo { + git rev-parse --is-inside-work-tree 2>$null | Out-Null + if ($LASTEXITCODE -ne 0) { + throw 'Run inside a git repository or pass -Repo.' + } +} + +function Get-RepoName { + param([string]$Name) + if ($Name) { return $Name } + return (Split-Path -Leaf (git rev-parse --show-toplevel)) +} + +function Set-Remote { + param( + [string]$Name, + [string]$Url + ) + + $existing = git remote 2>$null + $has = $existing -contains $Name + + if ($WhatIf) { + Write-Step "WhatIf: remote $Name -> $Url" + return + } + + if ($has) { + $current = (git remote get-url $Name 2>$null).Trim() + if ($current -eq $Url) { + Write-Ok "remote $Name OK" + return + } + git remote set-url $Name $Url + Write-Ok "remote $Name updated -> $Url" + return + } + + $legacy = @{ + home = @('gitea', 'papatramp', 'origin-home') + github = @('origin') + kalinamall = @('gitea-kalinamall', 'kalina') + } + foreach ($old in $legacy[$Name]) { + if ($existing -contains $old) { + git remote rename $old $Name + git remote set-url $Name $Url + Write-Ok "remote $old renamed to $Name -> $Url" + return + } + } + + git remote add $Name $Url + Write-Ok "remote $Name added -> $Url" +} + +Test-GitRepo +$repoName = Get-RepoName -Name $Repo + +$homeUrl = "ssh://git@git.papatramp.lan:2222/${Owner}/${repoName}.git" +$kalinamallUrl = "ssh://git@git.kalinamall.lan:2222/${Owner}/${repoName}.git" +$githubUrl = "git@github.com:${GithubOrg}/${repoName}.git" + +Write-Step "Repo: $repoName" +Set-Remote -Name 'home' -Url $homeUrl +Set-Remote -Name 'github' -Url $githubUrl +if (-not $SkipKalinamall) { + Set-Remote -Name 'kalinamall' -Url $kalinamallUrl +} + +Write-Host '' +Write-Host 'Remotes:' -ForegroundColor Magenta +git remote -v