feat: workspace-bootstrap — init SSH/git/Cursor для Mac и Windows
Единый workspace.local.env для адресов и паролей, init-machine, Set-GitRemotes, push-safe и check-no-secrets для политики kalinamall/github.
This commit is contained in:
+5
-1
@@ -1,3 +1,7 @@
|
|||||||
# Секреты и ключи
|
# Секреты и ключи
|
||||||
*.pem
|
*.pem
|
||||||
*.key
|
*.key
|
||||||
|
|
||||||
|
# Workspace bootstrap — локальные секреты (только на машине)
|
||||||
|
scripts/workspace-bootstrap/config/workspace.local.env
|
||||||
|
**/workspace.local.env
|
||||||
|
|||||||
+7
-3
@@ -1,4 +1,4 @@
|
|||||||
# Работа с Git
|
# Работа с Git
|
||||||
|
|
||||||
Три **SSH**-remote (без HTTPS и без `origin`):
|
Три **SSH**-remote (без HTTPS и без `origin`):
|
||||||
|
|
||||||
@@ -25,12 +25,16 @@ git clone ssh://git@git.kalinamall.lan:2222/PapaTramp/reverse-proxy.git
|
|||||||
cd reverse-proxy
|
cd reverse-proxy
|
||||||
```
|
```
|
||||||
|
|
||||||
На Windows после [Setup-SshAccess](https://git.kalinamall.ru/PapaTramp/Answer.and.other.shit) (или локально):
|
На Windows:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Set-GitRemotes.ps1 -Repo reverse-proxy
|
cd scripts\workspace-bootstrap
|
||||||
|
.\init-machine.ps1
|
||||||
|
.\scripts\Set-GitRemotes.ps1 -Repo reverse-proxy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Полная настройка новой машины: [scripts/workspace-bootstrap/README.md](../scripts/workspace-bootstrap/README.md).
|
||||||
|
|
||||||
## Обновление локальной копии
|
## Обновление локальной копии
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
+22
-4
@@ -1,4 +1,4 @@
|
|||||||
# Политика репозиториев: git.kalinamall.ru и GitHub
|
# Политика репозиториев: git.kalinamall.ru и GitHub
|
||||||
|
|
||||||
Для перечисленных проектов действует единая схема: **основное хранилище — корпоративный Gitea**, **GitHub — резервная копия без секретов**.
|
Для перечисленных проектов действует единая схема: **основное хранилище — корпоративный Gitea**, **GitHub — резервная копия без секретов**.
|
||||||
|
|
||||||
@@ -37,13 +37,31 @@
|
|||||||
|
|
||||||
## Настройка remotes (один раз на машине)
|
## Настройка remotes (один раз на машине)
|
||||||
|
|
||||||
Только **SSH**, три имени (скрипт `Set-GitRemotes.ps1` из Answer.and.other.shit):
|
Только **SSH**, три имени — скрипт **`scripts/workspace-bootstrap`** (Mac/Linux: `Set-GitRemotes.sh`, Windows: `Set-GitRemotes.ps1`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/Documents/Cursor/Projects/reverse-proxy/scripts/workspace-bootstrap
|
||||||
|
cp config/workspace.local.env.example config/workspace.local.env
|
||||||
|
# заполнить workspace.local.env
|
||||||
|
./init-machine.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Или для одного репо:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/Set-GitRemotes.sh reverse-proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd C:\Users\papat\Projects\reverse-proxy
|
cd C:\Users\papat\Projects\reverse-proxy\scripts\workspace-bootstrap
|
||||||
..\Answer.and.other.shit\scripts\ssh-setup\Set-GitRemotes.ps1 -Repo reverse-proxy
|
.\init-machine.ps1
|
||||||
|
..\scripts\Set-GitRemotes.ps1 -Repo reverse-proxy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Старый вариант (Answer.and.other.shit) — переносится в `scripts/workspace-bootstrap`.
|
||||||
|
|
||||||
Или вручную:
|
Или вручную:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Workspace bootstrap
|
||||||
|
|
||||||
|
Единая настройка **Mac / Windows** для Git (SSH), Cursor и политики push.
|
||||||
|
|
||||||
|
Целевое место в Gitea: репозиторий **Answer.and.other.shit** (можно скопировать эту папку в `scripts/workspace-bootstrap/`).
|
||||||
|
|
||||||
|
## Быстрый старт (новая машина)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Клонировать bootstrap (или весь Answer.and.other.shit)
|
||||||
|
cd scripts/workspace-bootstrap
|
||||||
|
|
||||||
|
# 2. Секреты и адреса — один файл (не в git!)
|
||||||
|
cp config/workspace.local.env.example config/workspace.local.env
|
||||||
|
# отредактировать workspace.local.env
|
||||||
|
|
||||||
|
# 3. Машина: SSH, git, клоны, remotes
|
||||||
|
./init-machine.sh
|
||||||
|
|
||||||
|
# 4. Cursor: правила в проекты
|
||||||
|
./init-cursor.sh
|
||||||
|
|
||||||
|
# 5. Добавить ~/.ssh/id_ed25519_kalinamall.pub в Gitea (kalinamall + home) и GitHub
|
||||||
|
./init-machine.sh --verify
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows (PowerShell):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd scripts\workspace-bootstrap
|
||||||
|
copy config\workspace.local.env.example config\workspace.local.env
|
||||||
|
# отредактировать
|
||||||
|
.\init-machine.ps1
|
||||||
|
.\init-cursor.sh # через Git Bash, или: bash init-cursor.sh
|
||||||
|
.\init-machine.ps1 -Verify
|
||||||
|
```
|
||||||
|
|
||||||
|
## Файлы
|
||||||
|
|
||||||
|
| Файл | В git | Назначение |
|
||||||
|
|------|-------|------------|
|
||||||
|
| `config/workspace.local.env.example` | да | шаблон |
|
||||||
|
| `config/workspace.local.env` | **нет** | логины, IP, пароли, пути |
|
||||||
|
| `config/repos.yaml` | да | список репозиториев |
|
||||||
|
| `config/ssh-config.template` | да | `~/.ssh/config` |
|
||||||
|
| `config/hosts.template` | да | строки для `/etc/hosts` или `C:\Windows\System32\drivers\etc\hosts` |
|
||||||
|
|
||||||
|
## Push
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/Documents/Cursor/Projects/reverse-proxy
|
||||||
|
../../reverse-proxy/scripts/workspace-bootstrap/push-safe.sh
|
||||||
|
# или из bootstrap: ./push-safe.sh /path/to/repo
|
||||||
|
```
|
||||||
|
|
||||||
|
- **kalinamall** — всегда (с секретами)
|
||||||
|
- **home** — если `PUSH_HOME=yes` в env
|
||||||
|
- **github** — только после `check-no-secrets.sh`
|
||||||
|
|
||||||
|
## Переменная окружения
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export WORKSPACE_ENV=/path/to/workspace.local.env
|
||||||
|
./init-machine.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
По умолчанию: `config/workspace.local.env` рядом со скриптами.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Строки для hosts (подставляются IP из workspace.local.env)
|
||||||
|
__GITEA_KALINAMALL_IP__ __GITEA_KALINAMALL_HOST__ __GITEA_KALINAMALL_HOST_PUBLIC__
|
||||||
|
__GITEA_KALINAMALL_IP__ sac.kalinamall.ru sac-api.kalinamall.ru
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Список репозиториев PapaTramp / PTah
|
||||||
|
# github: false — не добавлять remote github, не пушить на GitHub
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- name: reverse-proxy
|
||||||
|
github: true
|
||||||
|
|
||||||
|
- name: security-alert-center
|
||||||
|
github: true
|
||||||
|
|
||||||
|
- name: seaca
|
||||||
|
github: false
|
||||||
|
|
||||||
|
- name: rdp-login-monitor
|
||||||
|
github: true
|
||||||
|
github_name: RDP-login-monitor
|
||||||
|
|
||||||
|
- name: ssh-monitor
|
||||||
|
github: true
|
||||||
|
|
||||||
|
- name: Answer.and.other.shit
|
||||||
|
github: false
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Сгенерировано init-machine.sh — ручные правки могут быть перезаписаны
|
||||||
|
# Блок BEGIN WORKSPACE-BOOTSTRAP … END
|
||||||
|
|
||||||
|
Host github.com
|
||||||
|
User git
|
||||||
|
IdentityFile __SSH_KEY_PATH__
|
||||||
|
IdentitiesOnly yes
|
||||||
|
|
||||||
|
Host __GITEA_KALINAMALL_HOST__ __GITEA_KALINAMALL_HOST_PUBLIC__
|
||||||
|
User git
|
||||||
|
HostName __GITEA_KALINAMALL_HOST__
|
||||||
|
Port __GITEA_KALINAMALL_SSH_PORT__
|
||||||
|
IdentityFile __SSH_KEY_PATH__
|
||||||
|
IdentitiesOnly yes
|
||||||
|
|
||||||
|
Host __GITEA_HOME_HOST__ __GITEA_HOME_HOST_PUBLIC__
|
||||||
|
User git
|
||||||
|
HostName __GITEA_HOME_HOST__
|
||||||
|
Port __GITEA_HOME_SSH_PORT__
|
||||||
|
IdentityFile __SSH_KEY_PATH__
|
||||||
|
IdentitiesOnly yes
|
||||||
|
|
||||||
|
Host haproxy haproxy.kalinamall.ru __SSH_HAPROXY_IP__
|
||||||
|
User __SSH_HAPROXY_USER__
|
||||||
|
IdentityFile __SSH_KEY_PATH__
|
||||||
|
IdentitiesOnly yes
|
||||||
|
|
||||||
|
# END WORKSPACE-BOOTSTRAP
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Копия: config/workspace.local.env (не коммитить!)
|
||||||
|
# Все адреса, логины и пароли для init-скриптов — только в workspace.local.env
|
||||||
|
|
||||||
|
# --- Профиль машины: home-mac | home-win | work-win ---
|
||||||
|
MACHINE_PROFILE="home-mac"
|
||||||
|
|
||||||
|
# --- Git (identity) ---
|
||||||
|
GIT_USER_NAME="Your Name"
|
||||||
|
GIT_USER_EMAIL="you@example.com"
|
||||||
|
|
||||||
|
# --- SSH-ключ для Git (создаётся init-machine, если файла нет) ---
|
||||||
|
SSH_KEY_BASENAME="id_ed25519_kalinamall"
|
||||||
|
SSH_KEY_COMMENT="papatramp"
|
||||||
|
|
||||||
|
# --- Корпоративный Gitea (remote: kalinamall) ---
|
||||||
|
GITEA_KALINAMALL_HOST="git.kalinamall.lan"
|
||||||
|
GITEA_KALINAMALL_HOST_PUBLIC="git.kalinamall.ru"
|
||||||
|
GITEA_KALINAMALL_IP="192.168.160.129"
|
||||||
|
GITEA_KALINAMALL_SSH_PORT="2222"
|
||||||
|
GITEA_KALINAMALL_ORG="PapaTramp"
|
||||||
|
|
||||||
|
# --- Домашний Gitea (remote: home) ---
|
||||||
|
GITEA_HOME_HOST="git.papatramp.lan"
|
||||||
|
GITEA_HOME_HOST_PUBLIC="git.papatramp.ru"
|
||||||
|
GITEA_HOME_SSH_PORT="2222"
|
||||||
|
GITEA_HOME_ORG="PapaTramp"
|
||||||
|
|
||||||
|
# --- GitHub (remote: github) ---
|
||||||
|
GITHUB_USER="PTah"
|
||||||
|
|
||||||
|
# --- Каталог проектов ---
|
||||||
|
PROJECTS_DIR_MAC="${HOME}/Documents/Cursor/Projects"
|
||||||
|
PROJECTS_DIR_WIN="C:/Users/papat/Projects"
|
||||||
|
|
||||||
|
# --- Push ---
|
||||||
|
PUSH_HOME="yes"
|
||||||
|
PUSH_GITHUB="yes"
|
||||||
|
|
||||||
|
# --- /etc/hosts (опционально: yes — init добавит строки из hosts.template) ---
|
||||||
|
UPDATE_HOSTS="yes"
|
||||||
|
|
||||||
|
# --- SSH на серверы (для справки / будущих скриптов; не для git remote) ---
|
||||||
|
SSH_HAPROXY_IP="192.168.160.117"
|
||||||
|
SSH_HAPROXY_USER="papatramp"
|
||||||
|
SSH_HAPROXY_PASSWORD=""
|
||||||
|
|
||||||
|
SSH_GIT_SERVER_IP="192.168.160.129"
|
||||||
|
SSH_GIT_SERVER_USER="papatramp"
|
||||||
|
SSH_GIT_SERVER_PASSWORD=""
|
||||||
|
|
||||||
|
SSH_SAC_SERVER_IP="192.168.160.145"
|
||||||
|
SSH_SAC_SERVER_USER="papatramp"
|
||||||
|
SSH_SAC_SERVER_PASSWORD=""
|
||||||
|
|
||||||
|
# --- Админ / VPN (справочно) ---
|
||||||
|
ADMIN_PUBLIC_IP="5.100.81.121"
|
||||||
|
VPN_CIDR="192.168.128.0/17"
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
description: Политика remotes и push — kalinamall/home/github
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Git remotes (kalinamall.ru)
|
||||||
|
|
||||||
|
- **kalinamall** — основной Gitea, полный код и секреты. `git push kalinamall main`.
|
||||||
|
- **home** — домашний Gitea, полная копия.
|
||||||
|
- **github** — только резерв **без секретов**. Перед push: `check-no-secrets.sh`.
|
||||||
|
- Remotes только **SSH** (`ssh://`, `git@`). HTTPS и `origin` не использовать.
|
||||||
|
- Не коммитить в GitHub: `.env`, ключи, пароли, токены, `google-services.json`, prod credentials.
|
||||||
|
- См. `docs/repo-policy.md` в reverse-proxy.
|
||||||
|
|
||||||
|
# Cursor
|
||||||
|
|
||||||
|
- Отвечать на русском, если пользователь пишет по-русски.
|
||||||
|
- Коммиты только по явной просьбе пользователя.
|
||||||
Executable
+29
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Git pre-push: проверка секретов только для remote github
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
remote="${1:-}"
|
||||||
|
url="${2:-}"
|
||||||
|
|
||||||
|
[[ $remote == github ]] || exit 0
|
||||||
|
|
||||||
|
# Найти bootstrap от корня репо
|
||||||
|
repo_root=$(git rev-parse --show-toplevel)
|
||||||
|
checker=""
|
||||||
|
|
||||||
|
for candidate in \
|
||||||
|
"$repo_root/scripts/workspace-bootstrap/scripts/check-no-secrets.sh" \
|
||||||
|
"$repo_root/../reverse-proxy/scripts/workspace-bootstrap/scripts/check-no-secrets.sh" \
|
||||||
|
"$HOME/Documents/Cursor/Projects/reverse-proxy/scripts/workspace-bootstrap/scripts/check-no-secrets.sh"; do
|
||||||
|
if [[ -f $candidate ]]; then
|
||||||
|
checker=$candidate
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z $checker ]]; then
|
||||||
|
echo "pre-push: check-no-secrets.sh не найден — пропуск проверки"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec bash "$checker" github
|
||||||
Executable
+33
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
# shellcheck source=lib/common.sh
|
||||||
|
source "$ROOT/lib/common.sh"
|
||||||
|
|
||||||
|
load_workspace_env
|
||||||
|
|
||||||
|
PROJ=$(projects_dir)
|
||||||
|
RULES_SRC="$ROOT/cursor/rules"
|
||||||
|
|
||||||
|
[[ -d $RULES_SRC ]] || die "нет $RULES_SRC"
|
||||||
|
|
||||||
|
while read -r repo _gh; do
|
||||||
|
[[ -z $repo ]] && continue
|
||||||
|
dest="$PROJ/$repo/.cursor/rules"
|
||||||
|
if [[ -d $PROJ/$repo ]]; then
|
||||||
|
mkdir -p "$dest"
|
||||||
|
cp -f "$RULES_SRC"/*.mdc "$dest/" 2>/dev/null || true
|
||||||
|
log "cursor rules → $dest"
|
||||||
|
fi
|
||||||
|
done < <(each_repo)
|
||||||
|
|
||||||
|
# User rules (опционально — копия в ~/.cursor/rules если каталог есть)
|
||||||
|
USER_RULES="$HOME/.cursor/rules"
|
||||||
|
if [[ -d $(dirname "$USER_RULES") ]]; then
|
||||||
|
mkdir -p "$USER_RULES"
|
||||||
|
cp -f "$RULES_SRC"/*.mdc "$USER_RULES/" 2>/dev/null || true
|
||||||
|
log "cursor user rules → $USER_RULES"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "init-cursor готово"
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#Requires -Version 5.1
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Инициализация машины: SSH, git, клоны (Windows).
|
||||||
|
.DESCRIPTION
|
||||||
|
Вызывает init-machine.sh через Git Bash, если доступен.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[switch]$Verify
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$BootstrapRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$ShScript = Join-Path $BootstrapRoot 'init-machine.sh'
|
||||||
|
|
||||||
|
$envExample = Join-Path $BootstrapRoot 'config\workspace.local.env.example'
|
||||||
|
$envLocal = Join-Path $BootstrapRoot 'config\workspace.local.env'
|
||||||
|
if (-not (Test-Path $envLocal)) {
|
||||||
|
Write-Host "Создайте config\workspace.local.env из workspace.local.env.example" -ForegroundColor Yellow
|
||||||
|
if (Test-Path $envExample) {
|
||||||
|
Copy-Item $envExample $envLocal
|
||||||
|
Write-Host "Скопирован шаблон → workspace.local.env — заполните и запустите снова."
|
||||||
|
}
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$gitBash = @(
|
||||||
|
"${env:ProgramFiles}\Git\bin\bash.exe",
|
||||||
|
"${env:ProgramFiles(x86)}\Git\bin\bash.exe"
|
||||||
|
) | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||||
|
|
||||||
|
$args = @()
|
||||||
|
if ($Verify) { $args += '--verify' }
|
||||||
|
|
||||||
|
if ($gitBash) {
|
||||||
|
& $gitBash $ShScript @args
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Git Bash не найден. Установите Git for Windows или выполните вручную:" -ForegroundColor Red
|
||||||
|
Write-Host " bash init-machine.sh $($args -join ' ')"
|
||||||
|
exit 1
|
||||||
Executable
+116
@@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
# shellcheck source=lib/common.sh
|
||||||
|
source "$ROOT/lib/common.sh"
|
||||||
|
|
||||||
|
VERIFY=0
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--verify) VERIFY=1; shift ;;
|
||||||
|
-h | --help)
|
||||||
|
echo "Usage: init-machine.sh [--verify]"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*) die "unknown option: $1" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
load_workspace_env
|
||||||
|
|
||||||
|
log "профиль: ${MACHINE_PROFILE:-?}, OS: $(detect_os)"
|
||||||
|
|
||||||
|
# --- SSH key ---
|
||||||
|
KEY_PATH=$(ssh_key_path)
|
||||||
|
mkdir -p "$(ssh_home)"
|
||||||
|
if [[ ! -f $KEY_PATH ]]; then
|
||||||
|
log "создаю ключ $KEY_PATH"
|
||||||
|
ssh-keygen -t ed25519 -C "${SSH_KEY_COMMENT:-papatramp}@$(hostname -s 2>/dev/null || hostname)" -f "$KEY_PATH" -N ""
|
||||||
|
log "добавьте публичный ключ в Gitea (kalinamall + home) и GitHub:"
|
||||||
|
echo "----------"
|
||||||
|
cat "${KEY_PATH}.pub"
|
||||||
|
echo "----------"
|
||||||
|
else
|
||||||
|
log "ключ уже есть: $KEY_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- ssh config ---
|
||||||
|
TMP_BLOCK=$(mktemp)
|
||||||
|
render_template "$ROOT/config/ssh-config.template" "$TMP_BLOCK"
|
||||||
|
merge_ssh_config "$TMP_BLOCK"
|
||||||
|
rm -f "$TMP_BLOCK"
|
||||||
|
log "обновлён $(ssh_home)/config"
|
||||||
|
|
||||||
|
# --- known_hosts ---
|
||||||
|
for target in "${GITEA_KALINAMALL_HOST}:${GITEA_KALINAMALL_SSH_PORT}" \
|
||||||
|
"${GITEA_HOME_HOST}:${GITEA_HOME_SSH_PORT}" "github.com"; do
|
||||||
|
host=${target%%:*}
|
||||||
|
port=${target##*:}
|
||||||
|
if [[ $host == $port ]]; then port=22; fi
|
||||||
|
log "ssh-keyscan $host:$port"
|
||||||
|
ssh-keyscan -p "$port" "$host" 2>/dev/null >>"$(ssh_home)/known_hosts" || true
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- git global: только SSH, без credential prompts ---
|
||||||
|
if [[ -n ${GIT_USER_NAME:-} ]]; then
|
||||||
|
git config --global user.name "$GIT_USER_NAME"
|
||||||
|
fi
|
||||||
|
if [[ -n ${GIT_USER_EMAIL:-} ]]; then
|
||||||
|
git config --global user.email "$GIT_USER_EMAIL"
|
||||||
|
fi
|
||||||
|
git config --global credential.helper ""
|
||||||
|
git config --global url."git@github.com:".insteadOf "https://github.com/"
|
||||||
|
git config --global url."ssh://git@${GITEA_KALINAMALL_HOST}:${GITEA_KALINAMALL_SSH_PORT}/".insteadOf "https://${GITEA_KALINAMALL_HOST_PUBLIC}/"
|
||||||
|
git config --global url."ssh://git@${GITEA_HOME_HOST}:${GITEA_HOME_SSH_PORT}/".insteadOf "https://${GITEA_HOME_HOST_PUBLIC}/"
|
||||||
|
log "git global: SSH-only, credential.helper отключён"
|
||||||
|
|
||||||
|
# --- hosts (optional) ---
|
||||||
|
if [[ ${UPDATE_HOSTS:-no} == yes ]]; then
|
||||||
|
HOSTS_TMP=$(mktemp)
|
||||||
|
sed \
|
||||||
|
-e "s|__GITEA_KALINAMALL_IP__|${GITEA_KALINAMALL_IP}|g" \
|
||||||
|
-e "s|__GITEA_KALINAMALL_HOST__|${GITEA_KALINAMALL_HOST}|g" \
|
||||||
|
-e "s|__GITEA_KALINAMALL_HOST_PUBLIC__|${GITEA_KALINAMALL_HOST_PUBLIC}|g" \
|
||||||
|
"$ROOT/config/hosts.template" >"$HOSTS_TMP"
|
||||||
|
if [[ $(detect_os) == mac ]]; then
|
||||||
|
log "добавление в /etc/hosts (нужен sudo)"
|
||||||
|
while read -r line; do
|
||||||
|
[[ -z $line || $line == \#* ]] && continue
|
||||||
|
grep -qF "$line" /etc/hosts 2>/dev/null || echo "$line" | sudo tee -a /etc/hosts >/dev/null
|
||||||
|
done <"$HOSTS_TMP"
|
||||||
|
elif [[ $(detect_os) == win ]]; then
|
||||||
|
log "Windows: добавьте вручную в C:\\Windows\\System32\\drivers\\etc\\hosts:"
|
||||||
|
cat "$HOSTS_TMP"
|
||||||
|
fi
|
||||||
|
rm -f "$HOSTS_TMP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- clone + remotes ---
|
||||||
|
PROJ=$(projects_dir)
|
||||||
|
mkdir -p "$PROJ"
|
||||||
|
while read -r repo has_gh; do
|
||||||
|
[[ -z $repo ]] && continue
|
||||||
|
dest="$PROJ/$repo"
|
||||||
|
if [[ ! -d $dest/.git ]]; then
|
||||||
|
log "клонирование $repo"
|
||||||
|
git clone "$(kalinamall_remote_url "$repo")" "$dest" || log "клон не удался (сеть/ключ?) — настройте ключ и повторите"
|
||||||
|
fi
|
||||||
|
if [[ -d $dest/.git ]]; then
|
||||||
|
bash "$ROOT/scripts/Set-GitRemotes.sh" --repo-dir "$dest" "$repo" "$has_gh"
|
||||||
|
# pre-push hook для github
|
||||||
|
if [[ $has_gh == 1 && -f $ROOT/hooks/pre-push ]]; then
|
||||||
|
install -m 755 "$ROOT/hooks/pre-push" "$dest/.git/hooks/pre-push"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < <(each_repo)
|
||||||
|
|
||||||
|
if [[ $VERIFY == 1 ]]; then
|
||||||
|
log "проверка SSH (BatchMode — без запроса пароля)"
|
||||||
|
ssh -o BatchMode=yes -o ConnectTimeout=8 -p "$GITEA_KALINAMALL_SSH_PORT" -T "git@${GITEA_KALINAMALL_HOST}" 2>&1 | head -3 || true
|
||||||
|
ssh -o BatchMode=yes -o ConnectTimeout=8 -p "$GITEA_HOME_SSH_PORT" -T "git@${GITEA_HOME_HOST}" 2>&1 | head -3 || true
|
||||||
|
ssh -o BatchMode=yes -o ConnectTimeout=8 -T git@github.com 2>&1 | head -3 || true
|
||||||
|
log "если выше «Permission denied» — добавьте .pub в Gitea/GitHub и повторите --verify"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "готово"
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Общие функции workspace-bootstrap
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
BOOTSTRAP_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
die() { echo "workspace-bootstrap: error: $*" >&2; exit 1; }
|
||||||
|
log() { echo "[bootstrap] $*"; }
|
||||||
|
|
||||||
|
load_workspace_env() {
|
||||||
|
local env_file="${WORKSPACE_ENV:-$BOOTSTRAP_ROOT/config/workspace.local.env}"
|
||||||
|
[[ -f $env_file ]] || die "нет $env_file — скопируйте config/workspace.local.env.example и заполните"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
set -a
|
||||||
|
source "$env_file"
|
||||||
|
set +a
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_os() {
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Darwin) echo mac ;;
|
||||||
|
MINGW* | MSYS* | CYGWIN*) echo win ;;
|
||||||
|
*) echo linux ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_home() {
|
||||||
|
if [[ $(detect_os) == win ]]; then
|
||||||
|
if [[ -n ${HOME:-} ]]; then printf '%s/.ssh' "$HOME"
|
||||||
|
else printf '%s/.ssh' "$USERPROFILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
printf '%s/.ssh' "$HOME"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
projects_dir() {
|
||||||
|
local os
|
||||||
|
os=$(detect_os)
|
||||||
|
if [[ $os == mac ]]; then
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
eval echo "${PROJECTS_DIR_MAC:-$HOME/Documents/Cursor/Projects}"
|
||||||
|
elif [[ $os == win ]]; then
|
||||||
|
echo "${PROJECTS_DIR_WIN:-$HOME/Projects}"
|
||||||
|
else
|
||||||
|
eval echo "${PROJECTS_DIR_MAC:-$HOME/projects}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_key_path() {
|
||||||
|
printf '%s/%s' "$(ssh_home)" "${SSH_KEY_BASENAME:-id_ed25519_kalinamall}"
|
||||||
|
}
|
||||||
|
|
||||||
|
expand_path() {
|
||||||
|
local p=$1
|
||||||
|
if [[ $p == ~* ]]; then
|
||||||
|
p="${p/#\~/$HOME}"
|
||||||
|
fi
|
||||||
|
printf '%s' "$p"
|
||||||
|
}
|
||||||
|
|
||||||
|
render_template() {
|
||||||
|
local template=$1 dest=$2
|
||||||
|
local key_path
|
||||||
|
key_path=$(ssh_key_path)
|
||||||
|
[[ -f $key_path ]] || key_path="${key_path}.example"
|
||||||
|
sed \
|
||||||
|
-e "s|__SSH_KEY_PATH__|$key_path|g" \
|
||||||
|
-e "s|__GITEA_KALINAMALL_HOST__|${GITEA_KALINAMALL_HOST}|g" \
|
||||||
|
-e "s|__GITEA_KALINAMALL_HOST_PUBLIC__|${GITEA_KALINAMALL_HOST_PUBLIC}|g" \
|
||||||
|
-e "s|__GITEA_KALINAMALL_SSH_PORT__|${GITEA_KALINAMALL_SSH_PORT}|g" \
|
||||||
|
-e "s|__GITEA_HOME_HOST__|${GITEA_HOME_HOST}|g" \
|
||||||
|
-e "s|__GITEA_HOME_HOST_PUBLIC__|${GITEA_HOME_HOST_PUBLIC}|g" \
|
||||||
|
-e "s|__GITEA_HOME_SSH_PORT__|${GITEA_HOME_SSH_PORT}|g" \
|
||||||
|
-e "s|__SSH_HAPROXY_IP__|${SSH_HAPROXY_IP}|g" \
|
||||||
|
-e "s|__SSH_HAPROXY_USER__|${SSH_HAPROXY_USER}|g" \
|
||||||
|
"$template" >"$dest"
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_ssh_config() {
|
||||||
|
local block_file=$1
|
||||||
|
local ssh_config
|
||||||
|
ssh_config="$(ssh_home)/config"
|
||||||
|
mkdir -p "$(ssh_home)"
|
||||||
|
touch "$ssh_config"
|
||||||
|
if grep -q 'BEGIN WORKSPACE-BOOTSTRAP' "$ssh_config" 2>/dev/null; then
|
||||||
|
local tmp
|
||||||
|
tmp=$(mktemp)
|
||||||
|
awk '/# BEGIN WORKSPACE-BOOTSTRAP/{skip=1} !skip{print} /# END WORKSPACE-BOOTSTRAP/{skip=0}' "$ssh_config" >"$tmp"
|
||||||
|
mv "$tmp" "$ssh_config"
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
echo ""
|
||||||
|
echo "# BEGIN WORKSPACE-BOOTSTRAP"
|
||||||
|
cat "$block_file"
|
||||||
|
echo "# END WORKSPACE-BOOTSTRAP"
|
||||||
|
} >>"$ssh_config"
|
||||||
|
chmod 600 "$ssh_config" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
each_repo() {
|
||||||
|
local repos_file="$BOOTSTRAP_ROOT/config/repos.yaml"
|
||||||
|
[[ -f $repos_file ]] || die "missing $repos_file"
|
||||||
|
awk '
|
||||||
|
/^ - name:/ { if (n != "") print n, gh; n = $3; gh = 0 }
|
||||||
|
/github: true/ { gh = 1 }
|
||||||
|
/github: false/ { gh = 0 }
|
||||||
|
END { if (n != "") print n, gh }
|
||||||
|
' "$repos_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
github_repo_name() {
|
||||||
|
local name=$1
|
||||||
|
local repos_file="$BOOTSTRAP_ROOT/config/repos.yaml"
|
||||||
|
local custom
|
||||||
|
custom=$(awk -v repo="$name" '
|
||||||
|
$0 ~ "- name: " repo { found=1; next }
|
||||||
|
found && /github_name:/ { print $2; exit }
|
||||||
|
' "$repos_file")
|
||||||
|
if [[ -n $custom ]]; then
|
||||||
|
echo "$custom"
|
||||||
|
else
|
||||||
|
echo "$name"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
kalinamall_remote_url() {
|
||||||
|
local repo=$1
|
||||||
|
printf 'ssh://git@%s:%s/%s/%s.git' \
|
||||||
|
"$GITEA_KALINAMALL_HOST" "$GITEA_KALINAMALL_SSH_PORT" "$GITEA_KALINAMALL_ORG" "$repo"
|
||||||
|
}
|
||||||
|
|
||||||
|
home_remote_url() {
|
||||||
|
local repo=$1
|
||||||
|
printf 'ssh://git@%s:%s/%s/%s.git' \
|
||||||
|
"$GITEA_HOME_HOST" "$GITEA_HOME_SSH_PORT" "$GITEA_HOME_ORG" "$repo"
|
||||||
|
}
|
||||||
|
|
||||||
|
github_remote_url() {
|
||||||
|
local repo=$1
|
||||||
|
local gh_name
|
||||||
|
gh_name=$(github_repo_name "$repo")
|
||||||
|
printf 'git@%s:%s/%s.git' 'github.com' "$GITHUB_USER" "$gh_name"
|
||||||
|
}
|
||||||
Executable
+32
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
# shellcheck source=lib/common.sh
|
||||||
|
source "$ROOT/lib/common.sh"
|
||||||
|
|
||||||
|
REPO_DIR="${1:-.}"
|
||||||
|
[[ -d $REPO_DIR ]] || die "каталог не найден: $REPO_DIR"
|
||||||
|
cd "$REPO_DIR"
|
||||||
|
[[ -d .git ]] || die "не git: $REPO_DIR"
|
||||||
|
|
||||||
|
load_workspace_env
|
||||||
|
|
||||||
|
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||||
|
log "push-safe в $(pwd) ветка $BRANCH"
|
||||||
|
|
||||||
|
git push kalinamall "$BRANCH" || die "push kalinamall failed"
|
||||||
|
|
||||||
|
if [[ ${PUSH_HOME:-yes} == yes ]]; then
|
||||||
|
git push home "$BRANCH" || log "push home пропущен (сеть?)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${PUSH_GITHUB:-yes} == yes ]] && git remote | grep -qx github; then
|
||||||
|
bash "$ROOT/scripts/check-no-secrets.sh" || exit 1
|
||||||
|
git push github "$BRANCH" || die "push github failed"
|
||||||
|
log "github OK"
|
||||||
|
else
|
||||||
|
log "github remote нет или PUSH_GITHUB=no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "готово"
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#Requires -Version 5.1
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Repo,
|
||||||
|
|
||||||
|
[string]$RepoDir = ''
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$ScriptsDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$BootstrapRoot = Split-Path -Parent $ScriptsDir
|
||||||
|
$ShScript = Join-Path $ScriptsDir 'Set-GitRemotes.sh'
|
||||||
|
|
||||||
|
$gitBash = @(
|
||||||
|
"${env:ProgramFiles}\Git\bin\bash.exe",
|
||||||
|
"${env:ProgramFiles(x86)}\Git\bin\bash.exe"
|
||||||
|
) | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||||
|
|
||||||
|
$bashArgs = @($ShScript, $Repo)
|
||||||
|
if ($RepoDir) { $bashArgs = @($ShScript, '--repo-dir', $RepoDir, $Repo) }
|
||||||
|
|
||||||
|
if ($gitBash) {
|
||||||
|
& $gitBash @bashArgs
|
||||||
|
exit $LASTEXITCODE
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Git Bash не найден."
|
||||||
|
exit 1
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Настроить remotes для одного репозитория (только SSH)
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
# shellcheck source=../lib/common.sh
|
||||||
|
source "$SCRIPT_DIR/../lib/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: Set-GitRemotes.sh [--repo-dir PATH] REPO_NAME [HAS_GITHUB]
|
||||||
|
|
||||||
|
REPO_NAME каталог проекта (имя в repos.yaml)
|
||||||
|
HAS_GITHUB 1 или 0 (по умолчанию из repos.yaml)
|
||||||
|
|
||||||
|
Remotes: kalinamall, home, github (если включён). Без origin и без https.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
REPO_NAME=""
|
||||||
|
REPO_DIR=""
|
||||||
|
HAS_GITHUB=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--repo-dir) REPO_DIR=$2; shift 2 ;;
|
||||||
|
-h | --help) usage; exit 0 ;;
|
||||||
|
*)
|
||||||
|
if [[ -z $REPO_NAME ]]; then REPO_NAME=$1
|
||||||
|
else HAS_GITHUB=$1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n $REPO_NAME ]] || { usage; exit 1; }
|
||||||
|
|
||||||
|
load_workspace_env
|
||||||
|
|
||||||
|
if [[ -z $REPO_DIR ]]; then
|
||||||
|
REPO_DIR="$(projects_dir)/$REPO_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -d $REPO_DIR/.git ]] || die "не git-репозиторий: $REPO_DIR"
|
||||||
|
|
||||||
|
if [[ -z $HAS_GITHUB ]]; then
|
||||||
|
HAS_GITHUB=$(each_repo | awk -v n="$REPO_NAME" '$1==n{print $2; exit}')
|
||||||
|
[[ -n $HAS_GITHUB ]] || die "репозиторий $REPO_NAME не найден в repos.yaml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$REPO_DIR"
|
||||||
|
|
||||||
|
set_remote() {
|
||||||
|
local name=$1 url=$2
|
||||||
|
if git remote | grep -qx "$name"; then
|
||||||
|
git remote set-url "$name" "$url"
|
||||||
|
else
|
||||||
|
git remote add "$name" "$url"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Убрать origin/https если были
|
||||||
|
if git remote | grep -qx origin; then
|
||||||
|
local_url=$(git remote get-url origin 2>/dev/null || true)
|
||||||
|
if [[ $local_url == https://* ]]; then
|
||||||
|
log "удаляю origin с HTTPS: $local_url"
|
||||||
|
git remote remove origin
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
set_remote kalinamall "$(kalinamall_remote_url "$REPO_NAME")"
|
||||||
|
set_remote home "$(home_remote_url "$REPO_NAME")"
|
||||||
|
|
||||||
|
if [[ $HAS_GITHUB == 1 ]]; then
|
||||||
|
set_remote github "$(github_remote_url "$REPO_NAME")"
|
||||||
|
elif git remote | grep -qx github; then
|
||||||
|
log "удаляю github remote для $REPO_NAME (github: false)"
|
||||||
|
git remote remove github
|
||||||
|
fi
|
||||||
|
|
||||||
|
git branch -u kalinamall/main main 2>/dev/null || git branch -u kalinamall/main master 2>/dev/null || true
|
||||||
|
|
||||||
|
log "$REPO_NAME remotes:"
|
||||||
|
git remote -v
|
||||||
+75
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Блокирует push на github при подозрении на секреты в коммитах
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
# shellcheck source=lib/common.sh
|
||||||
|
source "$ROOT/lib/common.sh"
|
||||||
|
|
||||||
|
PATTERNS=(
|
||||||
|
'\.env$'
|
||||||
|
'SECRET_KEY'
|
||||||
|
'DATABASE_URL='
|
||||||
|
'password\s*=\s*["\x27][^"\x27]+'
|
||||||
|
'BEGIN (RSA |OPENSSH )?PRIVATE KEY'
|
||||||
|
'api[_-]?key'
|
||||||
|
'telegram.*token'
|
||||||
|
'smtp.*password'
|
||||||
|
'credentials\.json'
|
||||||
|
'google-services\.json'
|
||||||
|
'\.pem$'
|
||||||
|
'\.p12$'
|
||||||
|
'\.jks$'
|
||||||
|
)
|
||||||
|
|
||||||
|
scan_range() {
|
||||||
|
local range=$1
|
||||||
|
local hits=0
|
||||||
|
local files
|
||||||
|
files=$(git diff --name-only $range 2>/dev/null; git diff --cached --name-only 2>/dev/null)
|
||||||
|
files=$(echo "$files" | sort -u | grep -v '^$' || true)
|
||||||
|
while read -r f; do
|
||||||
|
[[ -z $f ]] && continue
|
||||||
|
[[ -f $f ]] || continue
|
||||||
|
case $f in
|
||||||
|
*.example | *.sample | *env.example | workspace.local.env.example) continue ;;
|
||||||
|
esac
|
||||||
|
for pat in "${PATTERNS[@]}"; do
|
||||||
|
if grep -qiE "$pat" "$f" 2>/dev/null; then
|
||||||
|
echo " SECRET? $f (pattern: $pat)"
|
||||||
|
hits=$((hits + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done <<<"$files"
|
||||||
|
return $hits
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local remote="${1:-github}"
|
||||||
|
local branch
|
||||||
|
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo main)
|
||||||
|
|
||||||
|
if ! git remote | grep -qx "$remote"; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local range=""
|
||||||
|
if git rev-parse "$remote/$branch" >/dev/null 2>&1; then
|
||||||
|
range="$remote/$branch..HEAD"
|
||||||
|
else
|
||||||
|
range="HEAD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[check-no-secrets] сканирование перед push $remote ($range)"
|
||||||
|
local n=0
|
||||||
|
scan_range "$range" || n=$?
|
||||||
|
|
||||||
|
if [[ $n -gt 0 ]]; then
|
||||||
|
echo "[check-no-secrets] найдено подозрительных совпадений: $n"
|
||||||
|
echo "push на $remote отменён. Проверьте diff или используйте только kalinamall."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[check-no-secrets] OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
main github
|
||||||
Reference in New Issue
Block a user