Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions .claude/hooks/setup-cloud.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/bin/bash
# SessionStart hook for Claude Code web (cloud sandbox).
# Skipped entirely when running locally (CLI/IDE).
set -euo pipefail

if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
exit 0
fi

echo "Cloud sandbox detected — running setup…"

# ── 1. apt over HTTPS (egress proxy workaround) ──────────
sudo sed -i \
's|http://archive.ubuntu.com|https://archive.ubuntu.com|g' \
/etc/apt/sources.list.d/ubuntu.sources
sudo sed -i \
's|http://security.ubuntu.com|https://security.ubuntu.com|g' \
/etc/apt/sources.list.d/ubuntu.sources
sudo apt-get update -qq

# ── 2. System packages ───────────────────────────────────
sudo apt-get install -y -qq \
libpq-dev libcairo2-dev libpango1.0-dev \
libgdk-pixbuf2.0-dev libffi-dev \
libgirepository1.0-dev libgtk-3-dev \
libldap2-dev libsasl2-dev python3-dev \
postgresql-plpython3-16

# ── 3. Polish locale + PostgreSQL restart ─────────────────
sudo locale-gen pl_PL.UTF-8
sudo pg_ctlcluster 16 main restart

# ── 4. PostgreSQL trust auth ──────────────────────────────
PG_HBA=/etc/postgresql/16/main/pg_hba.conf
sudo sed -i \
's/^local.*all.*all.*peer/local all all trust/' \
"$PG_HBA"
sudo sed -i \
's/^host.*all.*all.*127.0.0.1\/32.*scram-sha-256/host all all 127.0.0.1\/32 trust/' \
"$PG_HBA"
sudo pg_ctlcluster 16 main reload

# ── 5. Database ───────────────────────────────────────────
sudo -u postgres psql -c \
"SELECT 1 FROM pg_roles WHERE rolname='bpp'" \
| grep -q 1 \
|| sudo -u postgres psql -c \
"CREATE USER bpp WITH PASSWORD '' SUPERUSER;"
sudo -u postgres psql -tc \
"SELECT 1 FROM pg_database WHERE datname='bpp'" \
| grep -q 1 \
|| sudo -u postgres psql -c \
"CREATE DATABASE bpp OWNER bpp;"

# ── 6. Redis ──────────────────────────────────────────────
redis-cli ping >/dev/null 2>&1 \
|| redis-server --daemonize yes

# ── 7. .env ───────────────────────────────────────────────
if [ ! -f "$CLAUDE_PROJECT_DIR/.env" ]; then
cat > "$CLAUDE_PROJECT_DIR/.env" << 'DOTENV'
DJANGO_SETTINGS_MODULE="django_bpp.settings.local"
DEBUG=true
DJANGO_BPP_HOSTNAME="localhost"
DJANGO_BPP_SECRET_KEY="test-secret-key-for-local-dev"
DJANGO_BPP_DB_NAME="bpp"
DJANGO_BPP_DB_USER="bpp"
DJANGO_BPP_DB_PASSWORD=""
DJANGO_BPP_DB_HOST="localhost"
DJANGO_BPP_DB_PORT="5432"
DJANGO_BPP_DB_DISABLE_SSL=1
DJANGO_BPP_REDIS_HOST="localhost"
DJANGO_BPP_REDIS_PORT="6379"
DJANGO_BPP_REDIS_DB_CELERY="2"
DJANGO_BPP_REDIS_DB_SESSION="4"
DJANGO_BPP_REDIS_DB_CACHE="5"
DJANGO_BPP_REDIS_DB_LOCKS="6"
DJANGO_BPP_RABBITMQ_HOST="localhost"
DJANGO_BPP_RABBITMQ_PORT="5672"
DJANGO_BPP_RABBITMQ_USER="bpp"
DJANGO_BPP_RABBITMQ_PASS="bpp"
DJANGO_BPP_UZYWAJ_PUNKTACJI_WEWNETRZNEJ="0"
DJANGO_BPP_PUNKTUJ_MONOGRAFIE="0"
DJANGO_BPP_INLINE_DLA_AUTOROW="stacked"
DJANGO_BPP_THEME_NAME="app-blue"
DJANGO_BPP_SESSION_SECURITY_WARN_AFTER="25200"
DJANGO_BPP_SESSION_SECURITY_EXPIRE_AFTER="28800"
DJANGO_BPP_PASSWORD_DURATION_SECONDS="315360000"
DJANGO_BPP_USE_PASSWORD_HISTORY="1"
DJANGO_BPP_PASSWORD_HISTORY_COUNT="1"
DOTENV
fi

# ── 8. Python dependencies ────────────────────────────────
cd "$CLAUDE_PROJECT_DIR"
uv sync --all-extras || true

# psycopg2 workaround: install binary, fake dist-info
if ! python -c "import psycopg2" 2>/dev/null; then
uv pip install psycopg2-binary==2.9.11
SITE_PKG=$(.venv/bin/python -c \
"import site; print(site.getsitepackages()[0])")
mkdir -p "$SITE_PKG/psycopg2-2.9.11.dist-info"
cat > "$SITE_PKG/psycopg2-2.9.11.dist-info/METADATA" \
<< 'META'
Metadata-Version: 2.1
Name: psycopg2
Version: 2.9.11
META
cat > "$SITE_PKG/psycopg2-2.9.11.dist-info/RECORD" \
<< 'REC'
psycopg2/__init__.py,sha256=,
psycopg2-2.9.11.dist-info/METADATA,sha256=,
psycopg2-2.9.11.dist-info/RECORD,,
REC
echo "uv" > \
"$SITE_PKG/psycopg2-2.9.11.dist-info/INSTALLER"
cat > "$SITE_PKG/psycopg2-2.9.11.dist-info/WHEEL" \
<< 'WHL'
Wheel-Version: 1.0
Generator: manual
Root-Is-Purelib: false
Tag: cp311-cp311-linux_x86_64
WHL
fi

echo "Cloud setup complete."
15 changes: 15 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/setup-cloud.sh\""
}
]
}
]
}
}
7 changes: 5 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ pytest src/app_name/tests/

## Claude Code Web Environment Setup

For cloud sandbox setup instructions, see
[CLAUDE_CLOUD.md](CLAUDE_CLOUD.md).
Cloud sandbox setup runs automatically via a `SessionStart` hook
(`.claude/hooks/setup-cloud.sh`). The hook checks
`CLAUDE_CODE_REMOTE` and exits immediately on CLI — no manual
steps needed. For sandbox-specific notes (known test failures,
limitations), see [CLAUDE_CLOUD.md](CLAUDE_CLOUD.md).

## Key Commands (Quick Reference)

Expand Down
171 changes: 18 additions & 153 deletions CLAUDE_CLOUD.md
Original file line number Diff line number Diff line change
@@ -1,149 +1,9 @@
# Claude Code Web Environment Setup
# Claude Code Web Environment — Notes

When running in Claude Code web environment (cloud sandbox),
the following setup steps are needed before running tests.
These steps handle missing system packages, services, and
workarounds for network restrictions in the sandbox.
Cloud sandbox setup runs automatically via the `SessionStart`
hook in `.claude/hooks/setup-cloud.sh`. No manual steps needed.

## 1. Configure apt to use HTTPS (network proxy workaround)

The sandbox routes traffic through an egress proxy that only
allows HTTPS to whitelisted domains. Apt must use HTTPS:

```bash
# Switch apt sources to HTTPS
sudo sed -i \
's|http://archive.ubuntu.com|https://archive.ubuntu.com|g' \
/etc/apt/sources.list.d/ubuntu.sources
sudo sed -i \
's|http://security.ubuntu.com|https://security.ubuntu.com|g' \
/etc/apt/sources.list.d/ubuntu.sources
sudo apt-get update
```

## 2. Install system dependencies

```bash
sudo apt-get install -y \
libpq-dev libcairo2-dev libpango1.0-dev \
libgdk-pixbuf2.0-dev libffi-dev \
libgirepository1.0-dev libgtk-3-dev \
libldap2-dev libsasl2-dev python3-dev \
postgresql-plpython3-16
```

## 3. Generate Polish locale and restart PostgreSQL

```bash
sudo locale-gen pl_PL.UTF-8
sudo pg_ctlcluster 16 main restart
```

## 4. Configure PostgreSQL for local trust auth

```bash
sudo sed -i \
's/^local.*all.*all.*peer/local all all trust/' \
/etc/postgresql/16/main/pg_hba.conf
sudo sed -i \
's/^host.*all.*all.*127.0.0.1\/32.*scram-sha-256/host all all 127.0.0.1\/32 trust/' \
/etc/postgresql/16/main/pg_hba.conf
sudo pg_ctlcluster 16 main reload
```

## 5. Create database user and database

```bash
sudo -u postgres psql -c \
"CREATE USER bpp WITH PASSWORD '' SUPERUSER;"
sudo -u postgres psql -c \
"CREATE DATABASE bpp OWNER bpp;"
```

## 6. Start Redis

```bash
redis-server --daemonize yes
```

## 7. Create .env file

```bash
cat > .env << 'EOF'
DJANGO_SETTINGS_MODULE="django_bpp.settings.local"
DEBUG=true
DJANGO_BPP_HOSTNAME="localhost"
DJANGO_BPP_SECRET_KEY="test-secret-key-for-local-dev"
DJANGO_BPP_DB_NAME="bpp"
DJANGO_BPP_DB_USER="bpp"
DJANGO_BPP_DB_PASSWORD=""
DJANGO_BPP_DB_HOST="localhost"
DJANGO_BPP_DB_PORT="5432"
DJANGO_BPP_DB_DISABLE_SSL=1
DJANGO_BPP_REDIS_HOST="localhost"
DJANGO_BPP_REDIS_PORT="6379"
DJANGO_BPP_REDIS_DB_CELERY="2"
DJANGO_BPP_REDIS_DB_SESSION="4"
DJANGO_BPP_REDIS_DB_CACHE="5"
DJANGO_BPP_REDIS_DB_LOCKS="6"
DJANGO_BPP_RABBITMQ_HOST="localhost"
DJANGO_BPP_RABBITMQ_PORT="5672"
DJANGO_BPP_RABBITMQ_USER="bpp"
DJANGO_BPP_RABBITMQ_PASS="bpp"
DJANGO_BPP_UZYWAJ_PUNKTACJI_WEWNETRZNEJ="0"
DJANGO_BPP_PUNKTUJ_MONOGRAFIE="0"
DJANGO_BPP_INLINE_DLA_AUTOROW="stacked"
DJANGO_BPP_THEME_NAME="app-blue"
DJANGO_BPP_SESSION_SECURITY_WARN_AFTER="25200"
DJANGO_BPP_SESSION_SECURITY_EXPIRE_AFTER="28800"
DJANGO_BPP_PASSWORD_DURATION_SECONDS="315360000"
DJANGO_BPP_USE_PASSWORD_HISTORY="1"
DJANGO_BPP_PASSWORD_HISTORY_COUNT="1"
EOF
```

## 8. Install Python dependencies

```bash
uv sync --all-extras
```

**psycopg2 workaround:** Even with `libpq-dev` installed,
`uv sync` may still try to build `psycopg2` from source and
fail. If so, install `psycopg2-binary` and create a fake
dist-info so uv considers the dependency satisfied:

```bash
uv pip install psycopg2-binary==2.9.11

SITE_PKG=$(.venv/bin/python -c \
"import site; print(site.getsitepackages()[0])")
mkdir -p "$SITE_PKG/psycopg2-2.9.11.dist-info"

cat > "$SITE_PKG/psycopg2-2.9.11.dist-info/METADATA" << 'EOF'
Metadata-Version: 2.1
Name: psycopg2
Version: 2.9.11
EOF

cat > "$SITE_PKG/psycopg2-2.9.11.dist-info/RECORD" << 'EOF'
psycopg2/__init__.py,sha256=,
psycopg2-2.9.11.dist-info/METADATA,sha256=,
psycopg2-2.9.11.dist-info/RECORD,,
EOF

echo "uv" > \
"$SITE_PKG/psycopg2-2.9.11.dist-info/INSTALLER"

cat > "$SITE_PKG/psycopg2-2.9.11.dist-info/WHEEL" << 'EOF'
Wheel-Version: 1.0
Generator: manual
Root-Is-Purelib: false
Tag: cp311-cp311-linux_x86_64
EOF
```

## 9. Run tests (without Playwright)
## Running tests

Playwright browsers cannot be downloaded in the sandbox
(cdn.playwright.dev is not whitelisted). Run tests excluding
Expand All @@ -153,19 +13,24 @@ Playwright tests:
uv run pytest -m "not playwright" --maxfail 50
```

**Known sandbox-specific test failures** (not real bugs):
- Tests using VCR cassettes for external APIs (CrossRef,
DOI) fail because the egress proxy changes the host/port
in requests. These tests pass on a normal machine.
**Full test run (without Playwright) takes ~55 minutes** in
the sandbox environment on a single worker.

## Known sandbox-specific test failures

These are **not real bugs** — they pass on a normal machine:

- Tests using VCR cassettes for external APIs (CrossRef, DOI)
fail because the egress proxy changes the host/port in
requests.
- Affected test files:
- `src/bpp/tests/test_admin/test_crossref_api_helpers.py`
- `src/bpp/tests/test_admin/test_crossref_api_sync.py`
- `src/importer_publikacji/tests/test_views.py`
- `src/pbn_import/tests/test_admin_compression.py`

**Note:** Docker builds (`make build`, `docker compose up`)
do not work in the sandbox because Docker image layer CDN
(`*.r2.cloudflarestorage.com`) is not in the proxy allowlist.
## Docker

**Full test run (without Playwright) takes ~55 minutes** in
the sandbox environment on a single worker.
Docker builds (`make build`, `docker compose up`) do not work
in the sandbox because Docker image layer CDN
(`*.r2.cloudflarestorage.com`) is not in the proxy allowlist.
15 changes: 12 additions & 3 deletions src/bpp/tests/test_admin/test_crossref_api_sync_playwright.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ def autor_m():
)


@pytest.mark.vcr(ignore_localhost=True)
@pytest.mark.vcr(
match_on=("method", "scheme", "path", "query"),
ignore_localhost=True,
)
def test_crossref_api_autor_sync(
admin_page: Page, live_server, transactional_db, autor_m
):
Expand Down Expand Up @@ -81,7 +84,10 @@ def admin_page_strona_porownania(admin_page: Page, live_server):
return admin_page


@pytest.mark.vcr(ignore_localhost=True)
@pytest.mark.vcr(
match_on=("method", "scheme", "path", "query"),
ignore_localhost=True,
)
@pytest.mark.parametrize(
"id_przycisku, atrybut, wynik",
[
Expand Down Expand Up @@ -119,7 +125,10 @@ def check_attribute():
)


@pytest.mark.vcr(ignore_localhost=True)
@pytest.mark.vcr(
match_on=("method", "scheme", "path", "query"),
ignore_localhost=True,
)
def test_crossref_api_streszczenie_sync_browser(
transactional_db,
wydawnictwo_ciagle_jehs_2022,
Expand Down
Loading
Loading