samjeston / openhub Public
Sam Jeston Working vertical 9aa3c45 · History
151 lines· 7.8 KB ·Bourne Again Shell (bash)
Raw
1#!/usr/bin/env bash
2# End-to-end smoke test: starts a throwaway Openhub instance and exercises
3# sign up, SSH keys, pushing, browsing, pull requests, merging and permissions.
4#
5# Usage: scripts/smoke-test.sh [path/to/openhub-binary]
6set -euo pipefail
7
8ROOT="$(cd "$(dirname "$0")/.." && pwd)"
9BIN="${1:-$ROOT/target/debug/openhub}"
10HTTP_PORT="${HTTP_PORT:-38080}"
11SSH_PORT="${SSH_PORT:-38022}"
12BASE="http://127.0.0.1:$HTTP_PORT"
13
14if [[ ! -x "$BIN" ]]; then
15 (cd "$ROOT" && cargo build --quiet)
16fi
17
18WORK="$(mktemp -d)"
19SERVER_PID=""
20cleanup() {
21 [[ -n "$SERVER_PID" ]] && kill "$SERVER_PID" 2>/dev/null || true
22 rm -rf "$WORK"
23}
24trap cleanup EXIT
25
26pass=0
27ok() { pass=$((pass + 1)); printf ' \033[32m✓\033[0m %s\n' "$1"; }
28fail() {
29 printf ' \033[31m✗ %s\033[0m\n' "$1"
30 echo "--- server log ---"
31 tail -n 30 "$WORK/server.log" || true
32 exit 1
33}
34expect_status() { # expect_status <code> <description> <curl args...>
35 local want="$1" desc="$2"
36 shift 2
37 local got
38 got="$(curl -s -o /dev/null -w '%{http_code}' "$@")"
39 [[ "$got" == "$want" ]] && ok "$desc" || fail "$desc (expected $want, got $got)"
40}
41expect_body() { # expect_body <pattern> <description> <curl args...>
42 local pattern="$1" desc="$2"
43 shift 2
44 curl -s "$@" | grep -q -- "$pattern" && ok "$desc" || fail "$desc (missing '$pattern')"
45}
46
47echo "Starting Openhub in $WORK"
48"$BIN" --data-dir "$WORK/data" --http-addr "127.0.0.1:$HTTP_PORT" --ssh-addr "127.0.0.1:$SSH_PORT" \
49 --public-url "$BASE" >"$WORK/server.log" 2>&1 &
50SERVER_PID=$!
51for _ in $(seq 1 50); do
52 curl -s -o /dev/null "$BASE/" && break
53 sleep 0.2
54done
55curl -s -o /dev/null "$BASE/" || fail "server did not start"
56
57ssh-keygen -q -t ed25519 -N "" -C alice@test -f "$WORK/alice_key"
58ssh-keygen -q -t ed25519 -N "" -C bob@test -f "$WORK/bob_key"
59ssh_cmd() { echo "ssh -i $WORK/$1_key -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR"; }
60A_COOKIES="$WORK/alice.cookies"
61B_COOKIES="$WORK/bob.cookies"
62REMOTE="ssh://[email protected]:$SSH_PORT"
63
64echo "Accounts and keys"
65expect_status 303 "register alice (first user)" -c "$A_COOKIES" -X POST \
66 -d "username=alice&[email protected]&password=correct-horse" "$BASE/register"
67expect_status 303 "register bob" -c "$B_COOKIES" -X POST \
68 -d "username=bob&[email protected]&password=correct-horse" "$BASE/register"
69expect_status 303 "alice adds SSH key" -b "$A_COOKIES" -X POST \
70 --data-urlencode "key=$(cat "$WORK/alice_key.pub")" "$BASE/settings/keys"
71expect_status 303 "bob adds SSH key" -b "$B_COOKIES" -X POST \
72 --data-urlencode "key=$(cat "$WORK/bob_key.pub")" "$BASE/settings/keys"
73expect_body "already in use" "the same key cannot be added twice" -b "$B_COOKIES" -X POST \
74 --data-urlencode "key=$(cat "$WORK/alice_key.pub")" "$BASE/settings/keys"
75expect_body "Incorrect username or password" "wrong password is rejected" -X POST \
76 -d "login=alice&password=nope" "$BASE/login"
77greeting="$($(ssh_cmd alice) -T -p "$SSH_PORT" [email protected] 2>&1 || true)"
78[[ "$greeting" == *"Hi alice!"* ]] && ok "ssh -T greets alice" || fail "ssh -T greeting"
79
80echo "Repositories and pushing"
81expect_status 303 "create public repo" -b "$A_COOKIES" -X POST -d "name=demo&visibility=public" "$BASE/new"
82expect_status 303 "create private repo with README" -b "$A_COOKIES" -X POST \
83 -d "name=secret&visibility=private&readme=1" "$BASE/new"
84git init -q -b main "$WORK/demo"
85cd "$WORK/demo"
86git config user.name "Alice" && git config user.email [email protected]
87printf '# Demo\n\nHello from **Openhub**.\n' >README.md
88mkdir -p src && printf 'fn main() {\n println!("hi");\n}\n' >src/main.rs
89git add -A && git commit -qm "Initial commit"
90git remote add origin "$REMOTE/alice/demo.git"
91GIT_SSH_COMMAND="$(ssh_cmd alice)" git push -q -u origin main 2>/dev/null && ok "push over SSH" || fail "push over SSH"
92
93expect_body "Hello from <strong>Openhub</strong>" "README renders on repo page" "$BASE/alice/demo"
94expect_body 'tok-k' "source files are syntax highlighted" "$BASE/alice/demo/blob/main/src/main.rs"
95expect_body "Initial commit" "commit history lists the commit" "$BASE/alice/demo/commits/main"
96expect_status 200 "raw file download" "$BASE/alice/demo/raw/main/README.md"
97expect_status 200 "zip archive download" "$BASE/alice/demo/archive/main.zip"
98
99echo "Pull requests"
100git checkout -q -b feature
101printf 'pub fn add(a: i32, b: i32) -> i32 {\n a + b\n}\n' >src/lib.rs
102git add -A && git commit -qm "Add library"
103GIT_SSH_COMMAND="$(ssh_cmd alice)" git push -u origin feature 2>"$WORK/push.txt" >/dev/null
104grep -q "compare/main...feature" "$WORK/push.txt" && ok "push suggests opening a pull request" || fail "push hint"
105expect_status 303 "open pull request" -b "$A_COOKIES" -X POST \
106 -d "base=main&head=feature&title=Add+library&body=Adds+add()" "$BASE/alice/demo/pulls"
107expect_body "no conflicts" "pull request is mergeable" -b "$A_COOKIES" "$BASE/alice/demo/pull/1"
108expect_body "src/lib.rs" "files changed tab shows the diff" "$BASE/alice/demo/pull/1/files"
109expect_status 303 "bob comments" -b "$B_COOKIES" -X POST -d "body=Nice+work" "$BASE/alice/demo/pull/1/comment"
110expect_status 403 "bob cannot merge without write access" -b "$B_COOKIES" -X POST -d "method=merge" \
111 "$BASE/alice/demo/pull/1/merge"
112expect_status 303 "alice merges" -b "$A_COOKIES" -X POST -d "method=merge" "$BASE/alice/demo/pull/1/merge"
113expect_body "successfully merged" "pull request shows as merged" -b "$A_COOKIES" "$BASE/alice/demo/pull/1"
114GIT_SSH_COMMAND="$(ssh_cmd alice)" git fetch -q origin
115git log --format=%s origin/main | grep -q "Merge pull request #1" && ok "merge commit landed on main" || fail "merge commit"
116
117git checkout -q -b cli origin/main
118echo "x" >cli.txt && git add -A && git commit -qm "CLI change"
119GIT_SSH_COMMAND="$(ssh_cmd alice)" git push -q -u origin cli 2>/dev/null
120expect_status 303 "open second pull request" -b "$A_COOKIES" -X POST -d "base=main&head=cli&title=CLI" "$BASE/alice/demo/pulls"
121git checkout -q -B main origin/main && git merge -q --no-ff cli -m "Merge cli locally"
122GIT_SSH_COMMAND="$(ssh_cmd alice)" git push -q origin main 2>/dev/null
123expect_body "state-merged" "pull request merged on the command line is detected" -b "$A_COOKIES" "$BASE/alice/demo/pull/2"
124
125echo "Permissions"
126expect_status 404 "private repo hidden from anonymous users" "$BASE/alice/secret"
127expect_status 404 "private repo hidden from non-collaborators" -b "$B_COOKIES" "$BASE/alice/secret"
128GIT_SSH_COMMAND="$(ssh_cmd bob)" git clone -q "$REMOTE/alice/secret.git" "$WORK/nope" 2>/dev/null &&
129 fail "bob cloned a private repo" || ok "bob cannot clone private repo over SSH"
130cd "$WORK/demo"
131GIT_SSH_COMMAND="$(ssh_cmd bob)" git push -q origin HEAD:refs/heads/bob 2>/dev/null &&
132 fail "bob pushed without access" || ok "bob cannot push to alice/demo"
133expect_status 303 "alice adds bob as collaborator" -b "$A_COOKIES" -X POST -d "username=bob" \
134 "$BASE/alice/secret/settings/collaborators"
135GIT_SSH_COMMAND="$(ssh_cmd bob)" git clone -q "$REMOTE/alice/secret.git" "$WORK/secret" 2>/dev/null &&
136 ok "collaborator can clone private repo" || fail "collaborator clone"
137GIT_SSH_COMMAND="$(ssh_cmd alice)" git push -q origin HEAD:refs/pull/1/head 2>/dev/null &&
138 fail "pushed to refs/pull" || ok "refs/pull/* cannot be pushed to"
139
140echo "Git over HTTP"
141git clone -q "$BASE/alice/demo.git" "$WORK/http-clone" && ok "anonymous HTTP clone of public repo" || fail "HTTP clone"
142GIT_TERMINAL_PROMPT=0 git clone -q "$BASE/alice/secret.git" "$WORK/http-secret" 2>/dev/null &&
143 fail "anonymous HTTP clone of private repo" || ok "private repo requires authentication over HTTP"
144git clone -q "http://bob:[email protected]:$HTTP_PORT/alice/secret.git" "$WORK/http-secret2" &&
145 ok "collaborator HTTP clone with password" || fail "authenticated HTTP clone"
146cd "$WORK/http-clone"
147git -c user.name=x -c user.email=x@x commit -q --allow-empty -m "nope"
148git push -q origin main 2>/dev/null && fail "push over HTTP" || ok "push over HTTP is refused"
149
150echo
151printf '\033[32mAll %d checks passed.\033[0m\n' "$pass"