#!/usr/bin/env bash set -eo pipefail SCRIPT_DIR="$(dirname "$0")" COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" BASE_URL="${1:-http://localhost:13001}" SERVICE_NAME="${2:-forgejo-1}" ADMIN_USER="testadmin" ADMIN_PASS="admin1234" ADMIN_AUTH="$ADMIN_USER:$ADMIN_PASS" TESTBOT_AUTH="testbot:testbot1234" # --- Phase 1: Create users (sequential — prerequisite for everything) --- echo "Creating admin user..." docker compose -f "$COMPOSE_FILE" exec -T -u git "$SERVICE_NAME" \ forgejo admin user create --admin \ --username "$ADMIN_USER" \ --password "$ADMIN_PASS" \ --email testadmin@test.local \ --must-change-password=false echo "Creating testbot user..." docker compose -f "$COMPOSE_FILE" exec -T -u git "$SERVICE_NAME" \ forgejo admin user create \ --username testbot \ --password testbot1234 \ --email testbot@test.local \ --must-change-password=false echo "Creating readonlyuser..." docker compose -f "$COMPOSE_FILE" exec -T -u git "$SERVICE_NAME" \ forgejo admin user create \ --username readonlyuser \ --password readonly1234 \ --email readonlyuser@test.local \ --must-change-password=false # --- Phase 2: Create repositories (parallel) --- echo "Creating repositories..." curl -sf -X POST "$BASE_URL/api/v1/user/repos" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"name": "test-repo", "private": false, "auto_init": true}' & curl -sf -X POST "$BASE_URL/api/v1/user/repos" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"name": "test-repo-2", "description": "A second test repository", "private": false, "auto_init": true}' & curl -sf -X POST "$BASE_URL/api/v1/user/repos" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"name": "archived-repo", "description": "An archived repository", "private": false, "auto_init": true}' & wait echo "Repositories created." # Archive the archived-repo echo "Archiving archived-repo..." curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/archived-repo" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"archived": true}' # --- Phase 3: Create issues + code files + pagination issues (parallel) --- # Create 25 pagination issues sequentially in a background subshell # (sequential for deterministic issue numbering, background to overlap with other work) echo "Creating pagination test issues..." (for i in $(seq 1 25); do curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo-2/issues" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d "{\"title\": \"Pagination test issue $i\"}" done) & # Create issues 1-3 as testbot (generates notifications for testadmin) echo "Creating issues as testbot..." for i in 1 2 3; do curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues" \ -u "$TESTBOT_AUTH" \ -H "Content-Type: application/json" \ -d "{\"title\": \"Test issue $i from integration tests\"}" done # Phase 3b: Independent operations on test-repo (parallel) echo "Setting up test-repo content..." # Comment on issue #1 curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/1/comments" \ -u "$TESTBOT_AUTH" \ -H "Content-Type: application/json" \ -d '{"body": "This is a test comment from testbot"}' & # Add body text + close issue #3 in one PATCH curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/3" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"body": "This is the **markdown** body for issue 3.\n\nIt has multiple paragraphs.", "state": "closed"}' & # Body for issue #1 curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/1" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"body": "This is the **markdown** body for issue 1.\n\nIt has multiple paragraphs."}' & # Body for issue #2 curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/2" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"body": "This is the **markdown** body for issue 2.\n\nIt has multiple paragraphs."}' & # Code files (sequential — both commit to same branch) curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/contents/hello.py" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d "{\"content\": \"$(echo -n 'print(\"Hello from Forgejo!\")' | base64)\", \"message\": \"Add hello.py\"}" curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/contents/src/main.py" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d "{\"content\": \"$(echo -n 'def main():\n print(\"Main module\")' | base64)\", \"message\": \"Add src/main.py\"}" # Add testbot as collaborator curl -sf -X PUT "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/collaborators/testbot" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"permission": "write"}' & # Add readonlyuser as read-only collaborator curl -sf -X PUT "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/collaborators/readonlyuser" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"permission": "read"}' & # Create label curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/labels" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"name": "bug", "color": "#ee0701"}' & # Create milestone curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/milestones" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"title": "v1.0", "description": "First release milestone", "due_on": "2026-03-01T00:00:00Z"}' & wait echo "Phase 3 done." # --- Phase 3c: Metadata that depends on label/milestone existing --- # Label ID 1 and milestone ID 1 are deterministic because they're the first # created on a fresh Forgejo instance (auto-increment starts at 1). echo "Setting issue metadata..." # Add label to issue #1 (label ID 1 = "bug", created in Phase 3b) curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/1/labels" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"labels": [1]}' & # Set milestone + assignee on issue #1 (milestone ID 1 = "v1.0", created in Phase 3b) curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/1" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"milestone": 1, "assignees": ["testadmin"]}' & wait # --- Phase 4: Create branches + PRs (sequential — numbers must be deterministic #4, #5) --- echo "Creating feature branch..." curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/contents/feature.txt" \ -u "$TESTBOT_AUTH" \ -H "Content-Type: application/json" \ -d "{\"content\": \"$(echo -n 'This file was added in a feature branch' | base64)\", \"message\": \"Add feature.txt\", \"new_branch\": \"feature-branch\"}" echo "Creating pull request #4..." curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/pulls" \ -u "$TESTBOT_AUTH" \ -H "Content-Type: application/json" \ -d '{"title": "Add feature file", "head": "feature-branch", "base": "main", "body": "This PR adds a new feature file."}' echo "Creating merge branch..." curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/contents/merge-test.txt" \ -u "$TESTBOT_AUTH" \ -H "Content-Type: application/json" \ -d "{\"content\": \"$(echo -n 'This file is for merge testing' | base64)\", \"message\": \"Add merge-test.txt\", \"new_branch\": \"merge-branch\"}" echo "Creating pull request #5..." curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/pulls" \ -u "$TESTBOT_AUTH" \ -H "Content-Type: application/json" \ -d '{"title": "Merge test PR", "head": "merge-branch", "base": "main", "body": "This PR is for testing the merge flow."}' # --- Phase 5: Post-PR metadata (parallel) --- echo "Setting PR metadata..." # Comment on PR #4 curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/4/comments" \ -u "$TESTBOT_AUTH" \ -H "Content-Type: application/json" \ -d '{"body": "Please review this PR when you get a chance."}' & # Review on PR #4 curl -sf -X POST "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/pulls/4/reviews" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"event": "COMMENT", "body": "Looks good so far, just a few comments.", "comments": [{"path": "feature.txt", "body": "Consider a more descriptive filename.", "new_position": 1}]}' & # Milestone + assignee on PR #4 curl -sf -X PATCH "$BASE_URL/api/v1/repos/$ADMIN_USER/test-repo/issues/4" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"milestone": 1, "assignees": ["testadmin"]}' & wait # --- Phase 6: Create API token for token-based auth tests --- echo "Creating API token for testadmin..." TOKEN_RESPONSE=$(curl -sf -X POST "$BASE_URL/api/v1/users/$ADMIN_USER/tokens" \ -u "$ADMIN_AUTH" \ -H "Content-Type: application/json" \ -d '{"name": "integration-test-token", "scopes": ["read:user", "write:user", "read:repository", "write:repository", "read:issue", "write:issue", "read:notification", "write:notification", "read:organization"]}') API_TOKEN=$(echo "$TOKEN_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['sha1'])") echo "$API_TOKEN" > /tmp/forgejo_test_token.txt echo "API token written to /tmp/forgejo_test_token.txt" echo "" echo "Seed data created successfully."