fix: use Forgejo image as step container for CLI access (#668)
The install endpoint POST returned 404 because FORGEJO__database__DB_TYPE env var auto-configured Forgejo, bypassing install mode. Fix: run the Forgejo image as the step container instead of a service. This gives CLI access to `forgejo admin user create` for bootstrap admin setup — no install endpoint needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9c2a5634ff
commit
78e478e69d
2 changed files with 43 additions and 107 deletions
|
|
@ -1,24 +1,27 @@
|
||||||
# .woodpecker/smoke-init.yml — End-to-end smoke test for disinto init
|
# .woodpecker/smoke-init.yml — End-to-end smoke test for disinto init
|
||||||
#
|
#
|
||||||
# Starts a real Forgejo instance as a service container, then runs
|
# Uses the Forgejo image directly (not as a service) so we have CLI
|
||||||
# disinto init --bare --yes against it and verifies the results.
|
# access to set up Forgejo and create the bootstrap admin user.
|
||||||
|
# Then runs disinto init --bare --yes against the local Forgejo instance.
|
||||||
|
|
||||||
when:
|
when:
|
||||||
event: [push, pull_request]
|
event: [push, pull_request]
|
||||||
|
|
||||||
services:
|
|
||||||
- name: forgejo
|
|
||||||
image: codeberg.org/forgejo/forgejo:11.0
|
|
||||||
environment:
|
|
||||||
FORGEJO__database__DB_TYPE: sqlite3
|
|
||||||
FORGEJO__server__ROOT_URL: "http://forgejo:3000/"
|
|
||||||
FORGEJO__server__HTTP_PORT: "3000"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: smoke-init
|
- name: smoke-init
|
||||||
image: debian:bookworm-slim
|
image: codeberg.org/forgejo/forgejo:11.0
|
||||||
environment:
|
environment:
|
||||||
SMOKE_FORGE_URL: http://forgejo:3000
|
SMOKE_FORGE_URL: http://localhost:3000
|
||||||
commands:
|
commands:
|
||||||
- apt-get update -qq && apt-get install -y -qq --no-install-recommends bash curl jq python3 git ca-certificates >/dev/null 2>&1
|
# Install test dependencies (Alpine-based image)
|
||||||
|
- apk add --no-cache bash curl jq python3 git >/dev/null 2>&1
|
||||||
|
# Set up Forgejo data directories and config
|
||||||
|
- mkdir -p /data/gitea/conf /data/gitea/repositories /data/gitea/lfs /data/gitea/log /data/git/.ssh /data/ssh
|
||||||
|
- printf '[database]\nDB_TYPE = sqlite3\nPATH = /data/gitea/forgejo.db\n\n[server]\nHTTP_PORT = 3000\nROOT_URL = http://localhost:3000/\nLFS_START_SERVER = false\n\n[security]\nINSTALL_LOCK = true\n\n[service]\nDISABLE_REGISTRATION = true\n' > /data/gitea/conf/app.ini
|
||||||
|
# Start Forgejo in background and wait for it
|
||||||
|
- forgejo web --config /data/gitea/conf/app.ini &
|
||||||
|
- for i in $(seq 1 30); do curl -sf http://localhost:3000/api/v1/version >/dev/null 2>&1 && break; sleep 1; done
|
||||||
|
# Create bootstrap admin user via CLI (this is why we use the Forgejo image)
|
||||||
|
- forgejo admin user create --admin --username setup-admin --password "SetupPass-789xyz" --email "setup-admin@smoke.test" --must-change-password=false --config /data/gitea/conf/app.ini
|
||||||
|
# Run the smoke test
|
||||||
- bash tests/smoke-init.sh
|
- bash tests/smoke-init.sh
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# tests/smoke-init.sh — End-to-end smoke test for disinto init
|
# tests/smoke-init.sh — End-to-end smoke test for disinto init
|
||||||
#
|
#
|
||||||
# Runs against a real Forgejo instance (Woodpecker service container).
|
# Expects a running Forgejo at SMOKE_FORGE_URL with a bootstrap admin
|
||||||
|
# user already created (see .woodpecker/smoke-init.yml for CI setup).
|
||||||
# Validates the full init flow: Forgejo API, user/token creation,
|
# Validates the full init flow: Forgejo API, user/token creation,
|
||||||
# repo setup, labels, TOML generation, and cron installation.
|
# repo setup, labels, TOML generation, and cron installation.
|
||||||
#
|
#
|
||||||
# Required env: SMOKE_FORGE_URL (default: http://forgejo:3000)
|
# Required env: SMOKE_FORGE_URL (default: http://localhost:3000)
|
||||||
# Required tools: bash, curl, jq, python3, git
|
# Required tools: bash, curl, jq, python3, git
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
FACTORY_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
FACTORY_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
FORGE_URL="${SMOKE_FORGE_URL:-http://forgejo:3000}"
|
FORGE_URL="${SMOKE_FORGE_URL:-http://localhost:3000}"
|
||||||
SETUP_ADMIN="setup-admin"
|
SETUP_ADMIN="setup-admin"
|
||||||
SETUP_PASS="SetupPass-789xyz"
|
SETUP_PASS="SetupPass-789xyz"
|
||||||
SETUP_EMAIL="setup-admin@smoke.test"
|
|
||||||
TEST_SLUG="smoke-org/smoke-repo"
|
TEST_SLUG="smoke-org/smoke-repo"
|
||||||
MOCK_BIN="/tmp/smoke-mock-bin"
|
MOCK_BIN="/tmp/smoke-mock-bin"
|
||||||
MOCK_STATE="/tmp/smoke-mock-state"
|
MOCK_STATE="/tmp/smoke-mock-state"
|
||||||
|
|
@ -24,8 +24,8 @@ fail() { printf 'FAIL: %s\n' "$*" >&2; FAILED=1; }
|
||||||
pass() { printf 'PASS: %s\n' "$*"; }
|
pass() { printf 'PASS: %s\n' "$*"; }
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
rm -rf "$MOCK_BIN" "$MOCK_STATE" /tmp/smoke-test-repo /tmp/forgejo-cookies \
|
rm -rf "$MOCK_BIN" "$MOCK_STATE" /tmp/smoke-test-repo \
|
||||||
/tmp/install-page.html "${FACTORY_ROOT}/projects/smoke-repo.toml" \
|
"${FACTORY_ROOT}/projects/smoke-repo.toml" \
|
||||||
"${FACTORY_ROOT}/docker-compose.yml"
|
"${FACTORY_ROOT}/docker-compose.yml"
|
||||||
# Restore .env only if we created the backup
|
# Restore .env only if we created the backup
|
||||||
if [ -f "${FACTORY_ROOT}/.env.smoke-backup" ]; then
|
if [ -f "${FACTORY_ROOT}/.env.smoke-backup" ]; then
|
||||||
|
|
@ -43,68 +43,8 @@ fi
|
||||||
# Start with a clean .env (setup_forge writes tokens here)
|
# Start with a clean .env (setup_forge writes tokens here)
|
||||||
printf '' > "${FACTORY_ROOT}/.env"
|
printf '' > "${FACTORY_ROOT}/.env"
|
||||||
|
|
||||||
# ── 0. Wait for Forgejo HTTP ────────────────────────────────────────────────
|
# ── 1. Verify Forgejo is ready ──────────────────────────────────────────────
|
||||||
echo "=== 0/7 Waiting for Forgejo at ${FORGE_URL} ==="
|
echo "=== 1/6 Verifying Forgejo at ${FORGE_URL} ==="
|
||||||
retries=0
|
|
||||||
while true; do
|
|
||||||
if curl -sf --max-time 3 -o /dev/null "${FORGE_URL}/" 2>/dev/null; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
retries=$((retries + 1))
|
|
||||||
if [ "$retries" -gt 90 ]; then
|
|
||||||
fail "Forgejo not responsive after 90s"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
pass "Forgejo HTTP responsive (${retries}s)"
|
|
||||||
|
|
||||||
# ── 1. Complete Forgejo install ──────────────────────────────────────────────
|
|
||||||
echo "=== 1/7 Completing Forgejo initial setup ==="
|
|
||||||
|
|
||||||
# GET the install page to obtain CSRF token and session cookie
|
|
||||||
curl -sf -c /tmp/forgejo-cookies "${FORGE_URL}/install" \
|
|
||||||
-o /tmp/install-page.html 2>/dev/null || true
|
|
||||||
|
|
||||||
# Extract CSRF token (hidden input or meta tag)
|
|
||||||
csrf_token=""
|
|
||||||
if [ -f /tmp/install-page.html ]; then
|
|
||||||
csrf_token=$(grep '_csrf' /tmp/install-page.html \
|
|
||||||
| grep -oE '(content|value)="[^"]*"' \
|
|
||||||
| head -1 | cut -d'"' -f2) || csrf_token=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build POST data array
|
|
||||||
post_args=(
|
|
||||||
--data-urlencode "db_type=SQLite3"
|
|
||||||
--data-urlencode "db_path=/data/gitea/gitea.db"
|
|
||||||
--data-urlencode "app_name=Forgejo"
|
|
||||||
--data-urlencode "repo_root_path=/data/gitea/repositories"
|
|
||||||
--data-urlencode "lfs_root_path=/data/gitea/lfs"
|
|
||||||
--data-urlencode "run_user=git"
|
|
||||||
--data-urlencode "domain=forgejo"
|
|
||||||
--data-urlencode "ssh_port=22"
|
|
||||||
--data-urlencode "http_port=3000"
|
|
||||||
--data-urlencode "app_url=${FORGE_URL}/"
|
|
||||||
--data-urlencode "log_root_path=/data/gitea/log"
|
|
||||||
--data-urlencode "admin_name=${SETUP_ADMIN}"
|
|
||||||
--data-urlencode "admin_passwd=${SETUP_PASS}"
|
|
||||||
--data-urlencode "admin_confirm_passwd=${SETUP_PASS}"
|
|
||||||
--data-urlencode "admin_email=${SETUP_EMAIL}"
|
|
||||||
)
|
|
||||||
if [ -n "$csrf_token" ]; then
|
|
||||||
post_args+=(--data-urlencode "_csrf=${csrf_token}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
install_code=$(curl -s -b /tmp/forgejo-cookies \
|
|
||||||
-o /dev/null -w '%{http_code}' \
|
|
||||||
-X POST "${FORGE_URL}/install" \
|
|
||||||
"${post_args[@]}" 2>/dev/null) || install_code="000"
|
|
||||||
|
|
||||||
echo "Install POST returned HTTP ${install_code}"
|
|
||||||
|
|
||||||
# Wait for Forgejo API to become functional after install
|
|
||||||
echo -n "Waiting for Forgejo API"
|
|
||||||
retries=0
|
retries=0
|
||||||
api_version=""
|
api_version=""
|
||||||
while true; do
|
while true; do
|
||||||
|
|
@ -114,26 +54,24 @@ while true; do
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
retries=$((retries + 1))
|
retries=$((retries + 1))
|
||||||
if [ "$retries" -gt 60 ]; then
|
if [ "$retries" -gt 30 ]; then
|
||||||
echo ""
|
fail "Forgejo API not responding after 30s"
|
||||||
fail "Forgejo API not functional after install (60s)"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo -n "."
|
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
echo " ready (v${api_version})"
|
pass "Forgejo API v${api_version} (${retries}s)"
|
||||||
|
|
||||||
# Verify bootstrap admin user exists
|
# Verify bootstrap admin user exists
|
||||||
if curl -sf --max-time 5 "${FORGE_URL}/api/v1/users/${SETUP_ADMIN}" >/dev/null 2>&1; then
|
if curl -sf --max-time 5 "${FORGE_URL}/api/v1/users/${SETUP_ADMIN}" >/dev/null 2>&1; then
|
||||||
pass "Bootstrap admin '${SETUP_ADMIN}' created via install endpoint"
|
pass "Bootstrap admin '${SETUP_ADMIN}' exists"
|
||||||
else
|
else
|
||||||
fail "Bootstrap admin '${SETUP_ADMIN}' not found — install may have failed"
|
fail "Bootstrap admin '${SETUP_ADMIN}' not found — was Forgejo set up?"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── 2. Set up mock binaries ─────────────────────────────────────────────────
|
# ── 2. Set up mock binaries ─────────────────────────────────────────────────
|
||||||
echo "=== 2/7 Setting up mock binaries ==="
|
echo "=== 2/6 Setting up mock binaries ==="
|
||||||
mkdir -p "$MOCK_BIN" "$MOCK_STATE"
|
mkdir -p "$MOCK_BIN" "$MOCK_STATE"
|
||||||
|
|
||||||
# Store bootstrap admin credentials for the docker mock
|
# Store bootstrap admin credentials for the docker mock
|
||||||
|
|
@ -146,7 +84,7 @@ cat > "$MOCK_BIN/docker" << 'DOCKERMOCK'
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
FORGE_URL="${SMOKE_FORGE_URL:-http://forgejo:3000}"
|
FORGE_URL="${SMOKE_FORGE_URL:-http://localhost:3000}"
|
||||||
MOCK_STATE="/tmp/smoke-mock-state"
|
MOCK_STATE="/tmp/smoke-mock-state"
|
||||||
|
|
||||||
if [ ! -f "$MOCK_STATE/bootstrap_creds" ]; then
|
if [ ! -f "$MOCK_STATE/bootstrap_creds" ]; then
|
||||||
|
|
@ -266,20 +204,15 @@ chmod +x "$MOCK_BIN/crontab"
|
||||||
export PATH="$MOCK_BIN:$PATH"
|
export PATH="$MOCK_BIN:$PATH"
|
||||||
pass "Mock binaries installed (docker, claude, tmux, crontab)"
|
pass "Mock binaries installed (docker, claude, tmux, crontab)"
|
||||||
|
|
||||||
# ── 3. Prepare source repo ──────────────────────────────────────────────────
|
# ── 3. Run disinto init ─────────────────────────────────────────────────────
|
||||||
echo "=== 3/7 Preparing source repo ==="
|
echo "=== 3/6 Running disinto init ==="
|
||||||
# Configure git identity for the test (needed for any git operations)
|
rm -f "${FACTORY_ROOT}/projects/smoke-repo.toml"
|
||||||
|
|
||||||
|
# Configure git identity (needed for git operations)
|
||||||
git config --global user.email "smoke@test.local"
|
git config --global user.email "smoke@test.local"
|
||||||
git config --global user.name "Smoke Test"
|
git config --global user.name "Smoke Test"
|
||||||
|
|
||||||
pass "Git configured"
|
|
||||||
|
|
||||||
# ── 4. Run disinto init ─────────────────────────────────────────────────────
|
|
||||||
echo "=== 4/7 Running disinto init ==="
|
|
||||||
rm -f "${FACTORY_ROOT}/projects/smoke-repo.toml"
|
|
||||||
|
|
||||||
export SMOKE_FORGE_URL="$FORGE_URL"
|
export SMOKE_FORGE_URL="$FORGE_URL"
|
||||||
# FORGE_URL is read by lib/env.sh; override so init uses our test Forgejo
|
|
||||||
export FORGE_URL
|
export FORGE_URL
|
||||||
|
|
||||||
if bash "${FACTORY_ROOT}/bin/disinto" init \
|
if bash "${FACTORY_ROOT}/bin/disinto" init \
|
||||||
|
|
@ -292,8 +225,8 @@ else
|
||||||
fail "disinto init exited non-zero"
|
fail "disinto init exited non-zero"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── 5. Verify Forgejo state ─────────────────────────────────────────────────
|
# ── 4. Verify Forgejo state ─────────────────────────────────────────────────
|
||||||
echo "=== 5/7 Verifying Forgejo state ==="
|
echo "=== 4/6 Verifying Forgejo state ==="
|
||||||
|
|
||||||
# Admin user exists
|
# Admin user exists
|
||||||
if curl -sf --max-time 5 "${FORGE_URL}/api/v1/users/disinto-admin" >/dev/null 2>&1; then
|
if curl -sf --max-time 5 "${FORGE_URL}/api/v1/users/disinto-admin" >/dev/null 2>&1; then
|
||||||
|
|
@ -311,7 +244,7 @@ for bot in dev-bot review-bot; do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Repo exists (try org path, then fallback to dev-bot user path)
|
# Repo exists (try org path, then fallback paths)
|
||||||
repo_found=false
|
repo_found=false
|
||||||
for repo_path in "${TEST_SLUG}" "dev-bot/smoke-repo" "disinto-admin/smoke-repo"; do
|
for repo_path in "${TEST_SLUG}" "dev-bot/smoke-repo" "disinto-admin/smoke-repo"; do
|
||||||
if curl -sf --max-time 5 "${FORGE_URL}/api/v1/repos/${repo_path}" >/dev/null 2>&1; then
|
if curl -sf --max-time 5 "${FORGE_URL}/api/v1/repos/${repo_path}" >/dev/null 2>&1; then
|
||||||
|
|
@ -353,8 +286,8 @@ else
|
||||||
fail "Could not obtain verification token from bootstrap admin"
|
fail "Could not obtain verification token from bootstrap admin"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── 6. Verify local state ───────────────────────────────────────────────────
|
# ── 5. Verify local state ───────────────────────────────────────────────────
|
||||||
echo "=== 6/7 Verifying local state ==="
|
echo "=== 5/6 Verifying local state ==="
|
||||||
|
|
||||||
# TOML was generated
|
# TOML was generated
|
||||||
toml_path="${FACTORY_ROOT}/projects/smoke-repo.toml"
|
toml_path="${FACTORY_ROOT}/projects/smoke-repo.toml"
|
||||||
|
|
@ -398,8 +331,8 @@ else
|
||||||
fail "Repo not cloned to /tmp/smoke-test-repo"
|
fail "Repo not cloned to /tmp/smoke-test-repo"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── 7. Verify cron setup ────────────────────────────────────────────────────
|
# ── 6. Verify cron setup ────────────────────────────────────────────────────
|
||||||
echo "=== 7/7 Verifying cron setup ==="
|
echo "=== 6/6 Verifying cron setup ==="
|
||||||
cron_file="$MOCK_STATE/crontab-entries"
|
cron_file="$MOCK_STATE/crontab-entries"
|
||||||
if [ -f "$cron_file" ]; then
|
if [ -f "$cron_file" ]; then
|
||||||
if grep -q 'dev-poll.sh' "$cron_file"; then
|
if grep -q 'dev-poll.sh' "$cron_file"; then
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue