0d9ceff
commit 0d9ceff
1 file changed
+129 -0
Showing 1 changed file+129-0
▼scripts/e2e-proof.sh
+129-0
| @@ -0,0 +1,129 @@ | ||
1 | +#!/bin/bash | |
2 | +# OpenCodeHub full-stack E2E proof — real Postgres + Redis + app + real git | |
3 | +# | |
4 | +# Requirements: | |
5 | +# - app running on :4321 (see .env / docker-compose) | |
6 | +# - Postgres + Redis reachable via DATABASE_URL / REDIS_URL (127.0.0.1) | |
7 | +# - admin user seeded with password AdminPass123! (scripts/seed-admin.ts) | |
8 | +# - psql available with the DATABASE_DRIVER credentials for state reset | |
9 | +# | |
10 | +# Usage: | |
11 | +# PSQL_URL="postgresql://och:[email protected]:5432/opencodehub" \ | |
12 | +# bash scripts/e2e-proof.sh | |
13 | +set -u | |
14 | +BASE="${BASE_URL:-http://localhost:4321}" | |
15 | +PSQL_URL="${PSQL_URL:-postgresql://och:[email protected]:5432/opencodehub}" | |
16 | +COOKIE_JAR="$(mktemp)" | |
17 | +WORK="$(mktemp -d)" | |
18 | +PASS=0; FAIL=0 | |
19 | +ok() { PASS=$((PASS+1)); echo " ✅ $1"; } | |
20 | +bad() { FAIL=$((FAIL+1)); echo " ❌ $1"; } | |
21 | + | |
22 | +echo "== 0. Fresh state ==" | |
23 | +psql "$PSQL_URL" -tAc "DELETE FROM repositories; DELETE FROM organizations; DELETE FROM users WHERE username IN ('devuser');" > /dev/null 2>&1 || true | |
24 | +rm -rf "${GIT_REPOS_PATH:-./data/repos}"/* 2>/dev/null || true | |
25 | + | |
26 | +echo "== 1. Login as admin ==" | |
27 | +LOGIN=$(curl -s -c "$COOKIE_JAR" -X POST "$BASE/api/auth/login" -H "Content-Type: application/json" -d '{"login":"admin","password":"AdminPass123!"}') | |
28 | +echo "$LOGIN" | grep -q '"success":true' && ok "login" || bad "login: $LOGIN" | |
29 | + | |
30 | +echo "== 2. PAT + repo ==" | |
31 | +PAT=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/user/tokens" -H "Content-Type: application/json" -d '{"name":"e2e","expiresIn":"30d","scopes":["repo:write","admin"]}' | grep -o '"token":"och_[^"]*"' | cut -d'"' -f4) | |
32 | +[ -n "$PAT" ] && ok "PAT created" || bad "PAT failed" | |
33 | +REPO=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/repos" -H "Content-Type: application/json" -d '{"name":"e2e-prod","autoInit":true}') | |
34 | +echo "$REPO" | grep -qE 'e2e-prod|already' && ok "repo created" || bad "repo: $REPO" | |
35 | + | |
36 | +echo "== 3. Real git push (HTTP smart protocol with PAT) ==" | |
37 | +git init -q -b main "$WORK" && cd "$WORK" | |
38 | +git config user.email "[email protected]"; git config user.name "admin" | |
39 | +echo "# E2E" > README.md | |
40 | +mkdir -p .github/workflows | |
41 | +cat > .github/workflows/ci.yml << 'EOF' | |
42 | +name: CI | |
43 | +on: | |
44 | + push: | |
45 | + branches: [main] | |
46 | +jobs: | |
47 | + build: | |
48 | + runs-on: opencodehub | |
49 | + steps: | |
50 | + - run: echo "building $GITHUB_SHA" | |
51 | + lint: | |
52 | + runs-on: opencodehub | |
53 | + steps: | |
54 | + - run: echo "linting" | |
55 | +EOF | |
56 | +git add -A && git commit -qm "init with CI" | |
57 | +PUSH_OUT=$(timeout 60 git push "http://admin:$PAT@localhost:4321/git/admin/e2e-prod.git" main 2>&1) | |
58 | +echo "$PUSH_OUT" | grep -q "main -> main" && ok "git push (clean success)" || bad "push: $PUSH_OUT" | |
59 | +cd /tmp | |
60 | + | |
61 | +echo "== 4. Workflow run persisted + succeeds ==" | |
62 | +RUN_ID="" | |
63 | +for i in $(seq 1 20); do | |
64 | + sleep 3 | |
65 | + RUNS=$(curl -s -b "$COOKIE_JAR" "$BASE/api/repos/admin/e2e-prod/actions/runs" 2>/dev/null) | |
66 | + RUN_ID=$(echo "$RUNS" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4) | |
67 | + [ -n "$RUN_ID" ] && break | |
68 | +done | |
69 | +[ -n "$RUN_ID" ] && ok "run persisted ($RUN_ID)" || bad "no runs" | |
70 | +CONCLUSION="" | |
71 | +for i in $(seq 1 20); do | |
72 | + sleep 3 | |
73 | + RUN=$(curl -s -b "$COOKIE_JAR" "$BASE/api/repos/admin/e2e-prod/actions/runs/$RUN_ID" 2>/dev/null) | |
74 | + CONCLUSION=$(echo "$RUN" | grep -o '"conclusion":"[^"]*"' | head -1 | cut -d'"' -f4) | |
75 | + [ -n "$CONCLUSION" ] && break | |
76 | +done | |
77 | +[ "$CONCLUSION" = "success" ] && ok "CI run completed: success" || bad "run conclusion: $CONCLUSION" | |
78 | + | |
79 | +echo "== 5. PR + squash merge ==" | |
80 | +curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/repos/admin/e2e-prod/branches" -H "Content-Type: application/json" -d '{"name":"feature/e2e","from":"main"}' > /dev/null | |
81 | +PR=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/repos/admin/e2e-prod/pulls" -H "Content-Type: application/json" -d '{"title":"E2E PR","body":"Proof","base":"main","head":"feature/e2e"}') | |
82 | +PR_NUM=$(echo "$PR" | grep -o '"number":[0-9]*' | head -1 | cut -d: -f2) | |
83 | +[ -n "$PR_NUM" ] && ok "PR #$PR_NUM created" || bad "PR: ${PR:0:150}" | |
84 | +MERGE=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/repos/admin/e2e-prod/pulls/$PR_NUM/merge" -H "Content-Type: application/json" -d '{"mergeMethod":"squash"}') | |
85 | +echo "$MERGE" | grep -q success && ok "squash merge" || bad "merge: ${MERGE:0:150}" | |
86 | + | |
87 | +echo "== 6. OAuth provider flow ==" | |
88 | +APP=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/oauth/apps" -H "Content-Type: application/json" -d '{"name":"E2E App","redirectUris":["http://localhost:9999/cb"],"scopes":["repo:read"]}') | |
89 | +CID=$(echo "$APP" | grep -o '"clientId":"[^"]*"' | cut -d'"' -f4) | |
90 | +CSECRET=$(echo "$APP" | grep -o '"clientSecret":"[^"]*"' | cut -d'"' -f4) | |
91 | +[ -n "$CID" ] && ok "app registered" || bad "app: ${APP:0:150}" | |
92 | +AUTHZ=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/oauth/authorize" -d "client_id=$CID&redirect_uri=http%3A%2F%2Flocalhost%3A9999%2Fcb&state=xyz&approve=true&scope=repo%3Aread" -o /dev/null -w "%{redirect_url}") | |
93 | +CODE=$(echo "$AUTHZ" | grep -o 'code=[^&]*' | cut -d= -f2) | |
94 | +[ -n "$CODE" ] && ok "auth code issued" || bad "authz: $AUTHZ" | |
95 | +TOK=$(curl -s -X POST "$BASE/api/oauth/token" -d "grant_type=authorization_code&code=$CODE&client_id=$CID&client_secret=$CSECRET&redirect_uri=http%3A%2F%2Flocalhost%3A9999%2Fcb") | |
96 | +ATOKEN=$(echo "$TOK" | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4) | |
97 | +[ -n "$ATOKEN" ] && ok "access token issued" || bad "token: ${TOK:0:150}" | |
98 | +USERINFO=$(curl -s -H "Authorization: Bearer $ATOKEN" "$BASE/api/oauth/userinfo") | |
99 | +echo "$USERINFO" | grep -q '"username":"admin"' && ok "userinfo via bearer" || bad "userinfo: ${USERINFO:0:150}" | |
100 | + | |
101 | +echo "== 7. Org + invite + transfer ==" | |
102 | +curl -s -X POST "$BASE/api/auth/register" -H "Content-Type: application/json" -d '{"username":"devuser","email":"[email protected]","password":"DevPass123!"}' > /dev/null | |
103 | +DEVLOGIN=$(curl -s -c /tmp/och-dev-cookies.txt -X POST "$BASE/api/auth/login" -H "Content-Type: application/json" -d '{"login":"devuser","password":"DevPass123!"}') | |
104 | +echo "$DEVLOGIN" | grep -q '"success":true' && ok "second user created+login" || bad "dev user: $DEVLOGIN" | |
105 | +ORG_CREATE=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/orgs" -H "Content-Type: application/json" -d '{"name":"e2e-org","displayName":"E2E Org"}') | |
106 | +echo "$ORG_CREATE" | grep -qE 'e2e-org|already exists' && ok "org created (or pre-existing)" || bad "org create: $ORG_CREATE" | |
107 | +ORG_PAGE=$(curl -s -o /dev/null -w "%{http_code}" -b "$COOKIE_JAR" "$BASE/orgs/e2e-org") | |
108 | +[ "$ORG_PAGE" = "200" ] && ok "org page renders" || bad "org page: $ORG_PAGE" | |
109 | +INVITE=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/orgs/e2e-org/invites" -H "Content-Type: application/json" -d '{"username":"devuser"}') | |
110 | +INVITE_TOKEN=$(echo "$INVITE" | grep -o 'token=[^"]*' | head -1 | cut -d= -f2) | |
111 | +[ -n "$INVITE_TOKEN" ] && ok "invite created" || bad "invite: ${INVITE:0:150}" | |
112 | +ACCEPT=$(curl -s -b /tmp/och-dev-cookies.txt -X POST "$BASE/api/orgs/accept-invite" -H "Content-Type: application/json" -d "{\"token\":\"$INVITE_TOKEN\"}") | |
113 | +echo "$ACCEPT" | grep -q success && ok "invite accepted" || bad "accept: ${ACCEPT:0:150}" | |
114 | +TRANSFER=$(curl -s -b "$COOKIE_JAR" -X POST "$BASE/api/repos/admin/e2e-prod/transfer" -H "Content-Type: application/json" -d '{"orgName":"e2e-org"}') | |
115 | +echo "$TRANSFER" | grep -q success && ok "repo transferred to org" || bad "transfer: ${TRANSFER:0:150}" | |
116 | + | |
117 | +echo "== 8. Org-owned repo APIs + checks ==" | |
118 | +sleep 5 | |
119 | +CHECKS=$(curl -s -b "$COOKIE_JAR" "$BASE/api/repos/e2e-org/e2e-prod/pulls/$PR_NUM/checks" 2>/dev/null) | |
120 | +echo "$CHECKS" | grep -q '"success":true' && ok "PR checks on org-owned repo" || bad "checks: ${CHECKS:0:150}" | |
121 | +curl -s "$BASE/api/health" | grep -q '"ok":true\|"status":"ok"' && ok "health" || bad "health" | |
122 | + | |
123 | +echo "" | |
124 | +echo "════════════════════════════════════════" | |
125 | +echo " E2E RESULT: $PASS passed, $FAIL failed" | |
126 | +echo "════════════════════════════════════════" | |
127 | +rm -f "$COOKIE_JAR" /tmp/och-dev-cookies.txt | |
128 | +rm -rf "$WORK" | |
129 | +exit $FAIL | |
0 | 130 | |