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
|
||||
*.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`):
|
||||
|
||||
@@ -25,12 +25,16 @@ git clone ssh://git@git.kalinamall.lan:2222/PapaTramp/reverse-proxy.git
|
||||
cd reverse-proxy
|
||||
```
|
||||
|
||||
На Windows после [Setup-SshAccess](https://git.kalinamall.ru/PapaTramp/Answer.and.other.shit) (или локально):
|
||||
На Windows:
|
||||
|
||||
```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
|
||||
|
||||
+22
-4
@@ -1,4 +1,4 @@
|
||||
# Политика репозиториев: git.kalinamall.ru и GitHub
|
||||
# Политика репозиториев: git.kalinamall.ru и GitHub
|
||||
|
||||
Для перечисленных проектов действует единая схема: **основное хранилище — корпоративный Gitea**, **GitHub — резервная копия без секретов**.
|
||||
|
||||
@@ -37,13 +37,31 @@
|
||||
|
||||
## Настройка 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
|
||||
cd C:\Users\papat\Projects\reverse-proxy
|
||||
..\Answer.and.other.shit\scripts\ssh-setup\Set-GitRemotes.ps1 -Repo reverse-proxy
|
||||
cd C:\Users\papat\Projects\reverse-proxy\scripts\workspace-bootstrap
|
||||
.\init-machine.ps1
|
||||
..\scripts\Set-GitRemotes.ps1 -Repo reverse-proxy
|
||||
```
|
||||
|
||||
Старый вариант (Answer.and.other.shit) — переносится в `scripts/workspace-bootstrap`.
|
||||
|
||||
Или вручную:
|
||||
|
||||
```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