Skip to content

Commit 98871d5

Browse files
mpasternakclaude
andcommitted
feat(devsetup): prepare-developer-machine w bin/, detekcja dystrybucji, uv
Logika przeniesiona z Makefile do bin/prepare-developer-machine/. Skrypt rozpoznaje wersję macOS, architekturę i dystrybucję Linuksa (rodziny Debiana, Fedory/RHEL i Archa), a na Linuksie instaluje przypięte uv. Lista apt dostaje build-essential oraz nagłówki LDAP/SASL/SSL: python-ldap jest tylko jako sdist, więc bez nich uv sync pada na braku lber.h. Listy pakietów nie zostały zweryfikowane na prawdziwym Linuksie — testy w kontenerach przerwało wolne łącze. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mr7s9r131e98ET24qkVaAn
1 parent 4199235 commit 98871d5

8 files changed

Lines changed: 477 additions & 148 deletions

File tree

‎Makefile‎

Lines changed: 14 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -57,122 +57,21 @@ endif
5757

5858
all: prepare-developer-machine release ## UWAGA: pełna konfiguracja + release (uruchamia release!)
5959

60-
# WeasyPrint (cffi.dlopen / ctypes.util.find_library) musi znalezc
61-
# libgobject-2.0 / pango / harfbuzz / fontconfig zainstalowane przez brew.
62-
# Na Apple Silicon te biblioteki siedza w /opt/homebrew/lib, ktorego dyld
63-
# nie konsultuje domyslnie (default search path to /usr/local/lib + /usr/lib).
64-
#
65-
# Probowalismy wczesniej (commit 3531fd2d4) DYLD_FALLBACK_LIBRARY_PATH —
66-
# nie sprawdza sie w praktyce: macOS SIP strippuje wszystkie zmienne DYLD_*
67-
# w momencie wywolania chronionej binarki (/usr/bin/*, /bin/sh, itp.), wiec
68-
# w lancuchach typu make → sh → uv → python → pytest zmienna regularnie
69-
# ginie po drodze. Z perspektywy pytest/uv vs. dlopen — niedeterministyczne.
70-
#
71-
# Wracamy do symlinkow w /usr/local/lib: filesystem-level, dyld konsultuje
72-
# te sciezke z automatu, SIP nic z tym nie zrobi. Wymaga sudo *raz*
73-
# przy setupie maszyny. Idempotent — recipe nie nadpisuje istniejacych
74-
# symlinkow wskazujacych na te same cele.
75-
#
76-
# UWAGA: To runtime fix dla dlopen. Nie pomaga przy *build-time* bledach
77-
# (np. wheel buduje sie z zrodla i nie znajduje cairo.h) — wtedy potrzeba
78-
# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig + LDFLAGS=-L/opt/homebrew/lib
79-
# + CPPFLAGS=-I/opt/homebrew/include.
80-
prepare-developer-machine-macos: ## Zainstaluj zależności systemowe na macOS (brew + uv sync + playwright + symlinki)
81-
@if ! command -v brew >/dev/null 2>&1; then \
82-
echo ""; \
83-
echo "BŁĄD: Homebrew (brew) nie jest zainstalowany."; \
84-
echo ""; \
85-
echo "Homebrew jest wymagany do zainstalowania zależności systemowych"; \
86-
echo "(cairo, pango, gdk-pixbuf, libffi, gobject-introspection, gtk+3)."; \
87-
echo ""; \
88-
echo "Aby zainstalować Homebrew, uruchom w terminalu poniższe polecenie:"; \
89-
echo ""; \
90-
echo ' /bin/bash -c "$$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'; \
91-
echo ""; \
92-
echo "Po zakończeniu instalacji wykonaj kroki dodające 'brew' do PATH"; \
93-
echo "wypisane przez instalator (zwykle dla Apple Silicon: dopisanie"; \
94-
echo "linii 'eval \"\$$(/opt/homebrew/bin/brew shellenv)\"' do ~/.zprofile)."; \
95-
echo ""; \
96-
echo "Pełna dokumentacja: https://brew.sh"; \
97-
echo ""; \
98-
echo "Po instalacji Homebrew uruchom ponownie: make prepare-developer-machine"; \
99-
echo ""; \
100-
exit 1; \
101-
fi
102-
brew install cairo pango gdk-pixbuf libffi gobject-introspection gtk+3 node yarn
103-
npm install -g grunt-cli
104-
uv sync --frozen --no-install-project --all-extras
105-
@# Symlinki w /usr/local/lib — dyld konsultuje te sciezke domyslnie,
106-
@# wiec niezaleznie od stanu DYLD_* (SIP) WeasyPrint znajdzie libki.
107-
@if [ ! -d /usr/local/lib ]; then \
108-
echo "Tworze /usr/local/lib (wymagane sudo)..."; \
109-
sudo mkdir -p /usr/local/lib; \
110-
fi
111-
@for pair in \
112-
"/opt/homebrew/opt/glib/lib/libgobject-2.0.0.dylib:gobject-2.0" \
113-
"/opt/homebrew/opt/pango/lib/libpango-1.0.dylib:pango-1.0" \
114-
"/opt/homebrew/opt/harfbuzz/lib/libharfbuzz.dylib:harfbuzz" \
115-
"/opt/homebrew/opt/fontconfig/lib/libfontconfig.1.dylib:fontconfig-1" \
116-
"/opt/homebrew/opt/pango/lib/libpangoft2-1.0.dylib:pangoft2-1.0"; do \
117-
src="$${pair%:*}"; dst="/usr/local/lib/$${pair##*:}"; \
118-
if [ -L "$$dst" ] && [ "$$(readlink "$$dst")" = "$$src" ]; then \
119-
echo "Symlink $$dst juz wskazuje na $$src — pomijam."; \
120-
else \
121-
echo "Tworze symlink $$dst -> $$src (wymagane sudo)..."; \
122-
sudo ln -sf "$$src" "$$dst"; \
123-
fi; \
124-
done
125-
@# Cleanup po poprzedniej probie z DYLD_FALLBACK_LIBRARY_PATH —
126-
@# usun marker + linie export z ~/.zprofile, jesli zostaly.
127-
@ZPROFILE="$$HOME/.zprofile"; \
128-
MARKER='# bpp: weasyprint dlopen (Homebrew libs on Apple Silicon)'; \
129-
if [ -f "$$ZPROFILE" ] && grep -qF "$$MARKER" "$$ZPROFILE"; then \
130-
cp "$$ZPROFILE" "$$ZPROFILE.bpp-bak"; \
131-
awk -v m="$$MARKER" 'BEGIN{skip=0} \
132-
$$0==m {skip=1; next} \
133-
skip>0 {skip--; next} \
134-
{print}' "$$ZPROFILE.bpp-bak" > "$$ZPROFILE"; \
135-
echo "Usunieto stary wpis DYLD_FALLBACK_LIBRARY_PATH z $$ZPROFILE (backup: $$ZPROFILE.bpp-bak)."; \
136-
fi
137-
$(MAKE) playwright-install
138-
139-
prepare-developer-machine-linux: ## Zainstaluj zależności systemowe na Linuksie (apt + uv sync + playwright)
140-
sudo apt update
141-
sudo apt install -y yarnpkg nodejs npm python3-dev libpq-dev \
142-
libcairo2-dev libpango1.0-dev libgdk-pixbuf-xlib-2.0-dev libffi-dev \
143-
libgirepository1.0-dev libgtk-3-dev
144-
sudo npm install -g grunt-cli
145-
uv sync --frozen --no-install-project --all-extras
146-
$(MAKE) playwright-install
147-
148-
prepare-developer-machine: ## Zainstaluj zależności systemowe (auto-detekcja macOS/Linux)
149-
ifeq ($(OS),Darwin)
150-
$(MAKE) prepare-developer-machine-macos
151-
else ifeq ($(OS),Linux)
152-
$(MAKE) prepare-developer-machine-linux
153-
else
154-
@echo "Unsupported platform: $(OS)"
155-
@echo "Supported: Darwin (macOS), Linux"
156-
@exit 1
157-
endif
60+
# Właściwa logika (detekcja systemu i dystrybucji, pakiety, uv, Playwright)
61+
# siedzi w bin/prepare-developer-machine/.
62+
PREPARE_DEVELOPER_MACHINE := bin/prepare-developer-machine/prepare.sh
15863

159-
# Pobiera przeglądarki Playwright (chromium itd.) potrzebne do testów E2E.
160-
# Na Linuksie używa --with-deps, żeby playwright doinstalował systemowe
161-
# biblioteki (libnss3, libatk, libgtk-3...) przez apt — to wymaga sudo
162-
# i jest dokładnie tym, co opisuje README sekcja 2 ("uv run playwright
163-
# install" + "sudo playwright install-deps") tylko sklejone w jednej
164-
# komendzie. Na macOS install-deps to no-op (browsers są self-contained,
165-
# a brew już zainstalował systemowe libki w prepare-developer-machine-macos),
166-
# więc używamy gołego "playwright install".
167-
#
168-
# Wymaga, by uv sync --all-extras zostało wcześniej wykonane (playwright
169-
# CLI siedzi w grupie dev pyproject.toml). Stąd kolejność w prepare-*.
170-
playwright-install: ## Pobierz przeglądarki Playwright dla testów E2E (na Linuksie z --with-deps, sudo)
171-
ifeq ($(OS),Darwin)
172-
uv run playwright install
173-
else
174-
uv run playwright install --with-deps
175-
endif
64+
prepare-developer-machine-macos: ## Zainstaluj zależności systemowe na macOS (brew + uv + uv sync + playwright + symlinki)
65+
$(PREPARE_DEVELOPER_MACHINE) macos
66+
67+
prepare-developer-machine-linux: ## Zainstaluj zależności systemowe na Linuksie (apt/dnf/pacman + uv + uv sync + playwright)
68+
$(PREPARE_DEVELOPER_MACHINE) linux
69+
70+
prepare-developer-machine: ## Zainstaluj zależności systemowe (auto-detekcja systemu i dystrybucji)
71+
$(PREPARE_DEVELOPER_MACHINE)
72+
73+
playwright-install: ## Pobierz przeglądarki Playwright dla testów E2E (na Debianie/Ubuntu z --with-deps, sudo)
74+
$(PREPARE_DEVELOPER_MACHINE) playwright
17675

17776
prepare-claude: ## Pokaż instrukcję instalacji wtyczki claude-mem w Claude Code
17877
@echo "Setting up Claude Code with claude-mem plugin..."

‎README.md‎

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -141,32 +141,37 @@ uv run pytest -n auto # testy równolegle (pytest-xdist)
141141
```
142142

143143
Wymagania: **Docker daemon** (do testcontainers), Homebrew (macOS) lub
144-
`apt` + `sudo` (Linux). Pierwszy bieg pobiera kilkaset MB do paru GB
145-
(pakiety npm, przeglądarki Playwright, obrazy Dockera dla testów).
146-
147-
Co robi `make prepare-developer-machine`:
148-
149-
- **macOS** (Apple Silicon, Homebrew) — przez `brew`: `cairo`, `pango`,
150-
`gdk-pixbuf`, `libffi`, `gobject-introspection`, `gtk+3`, `node`,
151-
`yarn`; przez `npm` globalnie `grunt-cli`; tworzy `sudo`-symlinki
152-
w `/usr/local/lib` na libki z `/opt/homebrew/lib`
144+
`sudo` (Linux). `uv` instaluje się samo, jeśli go nie ma. Pierwszy bieg
145+
pobiera kilkaset MB do paru GB (pakiety npm, przeglądarki Playwright,
146+
obrazy Dockera dla testów).
147+
148+
Co robi `make prepare-developer-machine` (skrypty:
149+
`bin/prepare-developer-machine/`; system i dystrybucję wykrywa sam,
150+
`bin/prepare-developer-machine/prepare.sh detect` pokazuje wynik detekcji):
151+
152+
- **macOS** — przez `brew`: `cairo`, `pango`, `gdk-pixbuf`, `libffi`,
153+
`gobject-introspection`, `gtk+3`, `node`, `yarn`; przez `npm` globalnie
154+
`grunt-cli`; instaluje `uv`, jeśli go nie ma; na Apple Silicon tworzy
155+
`sudo`-symlinki w `/usr/local/lib` na libki z `/opt/homebrew/lib`
153156
(`dyld` nie konsultuje brew-owej ścieżki domyślnie, a `DYLD_FALLBACK_LIBRARY_PATH`
154157
jest stripowana przez SIP w podprocesach — patrz
155-
[docs/MACOS_WEASYPRINT.md](docs/MACOS_WEASYPRINT.md)); na końcu
156-
`uv sync --frozen --no-install-project --all-extras` +
158+
[docs/deweloper/weasyprint-macos.md](docs/deweloper/weasyprint-macos.md));
159+
na końcu `uv sync --frozen --no-install-project --all-extras` +
157160
`uv run playwright install`.
158-
- **Linux** (Debian/Ubuntu, `apt`) — przez `sudo apt`: `yarnpkg`,
159-
`nodejs`, `npm`, `python3-dev`, `libpq-dev`, `libcairo2-dev`,
160-
`libpango1.0-dev`, `libgdk-pixbuf2.0-dev`, `libffi-dev`,
161-
`libgirepository1.0-dev`, `libgtk-3-dev`; przez `sudo npm` globalnie
162-
`grunt-cli`; na końcu `uv sync --frozen --no-install-project
163-
--all-extras` + `uv run playwright install --with-deps` (z systemowymi
164-
libkami chromium — wymaga sudo).
165-
166-
Auto-detekcja systemu jest domyślna; aby wymusić wariant:
167-
`make prepare-developer-machine-macos` albo
168-
`make prepare-developer-machine-linux`. Cel **nie woła `make assets`** —
169-
frontend trzeba zbudować osobno.
161+
- **Linux** — pakiety systemowe (kompilator, nagłówki LDAP/SASL/SSL dla
162+
`python-ldap`, libki WeasyPrint, Node, yarn, gettext) i `grunt-cli`
163+
przez menedżer pakietów dystrybucji: `apt` (Debian, Ubuntu i pochodne),
164+
`dnf` (Fedora, RHEL i pochodne) albo `pacman` (Arch i pochodne); potem
165+
`uv` w wersji przypiętej w projekcie (do `~/.local/bin`, jeśli go nie
166+
ma) i `uv sync --frozen --no-install-project --all-extras`. Na końcu
167+
`uv run playwright install --with-deps` (Debian/Ubuntu, wymaga sudo)
168+
albo samo `uv run playwright install` — poza Debianem/Ubuntu Playwright
169+
nie jest oficjalnie wspierany, a jego biblioteki instaluje krok systemowy.
170+
171+
Aby wymusić wariant: `make prepare-developer-machine-macos` albo
172+
`make prepare-developer-machine-linux` (wariant niepasujący do systemu kończy
173+
się błędem). Cel **nie woła `make assets`** — frontend trzeba zbudować
174+
osobno.
170175

171176
`pytest -n auto` (`pytest-xdist`) rozdziela testy między workery; każdy
172177
worker dostaje **własny** testcontainer PostgreSQL/Redis na losowym
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# shellcheck shell=bash disable=SC2034
2+
#
3+
# Wspólne funkcje skryptów prepare-developer-machine: logowanie, detekcja
4+
# systemu, instalacja uv i przeglądarek Playwright.
5+
#
6+
# UWAGA: macOS ma bash 3.2 — bez tablic asocjacyjnych, `${x,,}` i `mapfile`.
7+
8+
# Trzymaj w parze z pinem uv w CI (`version:` w setup-uv), Dockerfile
9+
# (`COPY --from=ghcr.io/astral-sh/uv:…`) i .pre-commit-config.yaml. Inna wersja
10+
# potrafi uznać ten sam uv.lock za nieaktualny.
11+
UV_VERSION="0.13.5"
12+
13+
# Node z obrazów Dockera to 24 (NODEJS_VERSION w docker/bpp_base/Dockerfile).
14+
MIN_NODE_MAJOR=20
15+
16+
log() { printf '\n==> %s\n' "$*"; }
17+
warn() { printf 'UWAGA: %s\n' "$*" >&2; }
18+
die() {
19+
printf 'BŁĄD: %s\n' "$*" >&2
20+
exit 1
21+
}
22+
23+
# Ustawia DETECTED_OS na `macos` albo `linux`.
24+
detect_os() {
25+
case "$(uname -s)" in
26+
Darwin) DETECTED_OS=macos ;;
27+
Linux) DETECTED_OS=linux ;;
28+
*) die "Nieobsługiwany system: $(uname -s). Obsługiwane: macOS, Linux." ;;
29+
esac
30+
}
31+
32+
# Ustawia MACOS_VERSION, ARCH i BREW_PREFIX (pusty, gdy nie ma Homebrew).
33+
detect_macos() {
34+
MACOS_VERSION="$(sw_vers -productVersion)"
35+
ARCH="$(uname -m)"
36+
BREW_PREFIX=""
37+
if command -v brew >/dev/null 2>&1; then
38+
BREW_PREFIX="$(brew --prefix)"
39+
fi
40+
}
41+
42+
# Ustawia LINUX_ID, LINUX_VERSION_ID, LINUX_NAME, ARCH i LINUX_FAMILY
43+
# (`debian`, `fedora`, `arch` albo pusty, gdy dystrybucja jest nieobsługiwana).
44+
# ID_LIKE pozwala rozpoznać pochodne: Mint, Pop!_OS, Rocky, Manjaro itd.
45+
detect_linux() {
46+
local os_release="${OS_RELEASE_FILE:-/etc/os-release}"
47+
[ -r "$os_release" ] || die "Brak $os_release — nie rozpoznam dystrybucji."
48+
49+
local ID="" ID_LIKE="" VERSION_ID="" PRETTY_NAME=""
50+
# shellcheck disable=SC1090
51+
. "$os_release"
52+
53+
LINUX_ID="$ID"
54+
LINUX_VERSION_ID="$VERSION_ID"
55+
LINUX_NAME="${PRETTY_NAME:-$ID}"
56+
ARCH="$(uname -m)"
57+
LINUX_FAMILY=""
58+
59+
local candidate
60+
for candidate in $ID $ID_LIKE; do
61+
case "$candidate" in
62+
debian | ubuntu) LINUX_FAMILY=debian ;;
63+
fedora | rhel | centos) LINUX_FAMILY=fedora ;;
64+
arch) LINUX_FAMILY=arch ;;
65+
esac
66+
[ -z "$LINUX_FAMILY" ] || break
67+
done
68+
}
69+
70+
# Przypina uv, gdy go nie ma; instalator z astral.sh trafia do ~/.local/bin.
71+
# Na PATH dokładamy ten katalog zawsze, żeby znaleźć uv z poprzedniego
72+
# uruchomienia, gdy shell nie wczytał jeszcze zmienionego profilu.
73+
ensure_uv() {
74+
export PATH="$HOME/.local/bin:$PATH"
75+
76+
if command -v uv >/dev/null 2>&1; then
77+
local current
78+
current="$(uv --version | awk '{print $2}')"
79+
if [ "$current" = "$UV_VERSION" ]; then
80+
log "uv $current już zainstalowane — pomijam."
81+
else
82+
warn "uv $current różni się od wersji projektu ($UV_VERSION)."
83+
warn "Zaktualizuj: uv self update $UV_VERSION"
84+
fi
85+
return
86+
fi
87+
88+
command -v curl >/dev/null 2>&1 || die "Do instalacji uv potrzebny jest curl."
89+
log "Instaluję uv $UV_VERSION"
90+
curl -LsSf "https://astral.sh/uv/${UV_VERSION}/install.sh" | sh
91+
command -v uv >/dev/null 2>&1 ||
92+
die "uv zainstalowane, ale nie ma go na PATH (sprawdź ~/.local/bin)."
93+
warn "uv jest w ~/.local/bin — otwórz nowy shell, żeby było na PATH."
94+
}
95+
96+
sync_python_deps() {
97+
log "Synchronizuję zależności Pythona"
98+
uv sync --frozen --no-install-project --all-extras
99+
}
100+
101+
warn_if_old_node() {
102+
local major
103+
major="$(node --version | sed -E 's/^v([0-9]+).*/\1/')"
104+
if [ "$major" -lt "$MIN_NODE_MAJOR" ]; then
105+
warn "Node $major jest stary (obrazy Dockera używają 24)."
106+
warn "\`make assets\` może się nie udać — doinstaluj nowszy Node."
107+
fi
108+
}
109+
110+
# Wymaga wcześniejszego `uv sync --all-extras` (playwright CLI siedzi w grupie
111+
# dev). `--with-deps` doinstalowuje biblioteki systemowe przez apt (sudo),
112+
# więc działa tylko na rodzinie Debiana. Na macOS przeglądarki są
113+
# samowystarczalne, a na Fedorze/Archu biblioteki instaluje linux.sh.
114+
install_playwright_browsers() {
115+
export PATH="$HOME/.local/bin:$PATH"
116+
detect_os
117+
118+
log "Instaluję przeglądarki Playwright"
119+
if [ "$DETECTED_OS" = linux ]; then
120+
detect_linux
121+
if [ "$LINUX_FAMILY" = debian ]; then
122+
uv run playwright install --with-deps
123+
return
124+
fi
125+
warn "Playwright oficjalnie wspiera tylko Debiana i Ubuntu."
126+
fi
127+
uv run playwright install
128+
}

0 commit comments

Comments
 (0)