Files
gitea/docs/testing-guide-v1.26.md
logikonline b8b276fa05
Some checks failed
Build and Release / Lint and Test (push) Successful in 4m46s
Build and Release / Build Binaries (amd64, linux) (push) Failing after 42s
Build and Release / Build Binaries (amd64, darwin) (push) Has been cancelled
Build and Release / Build Binaries (amd64, windows) (push) Has been cancelled
Build and Release / Build Binaries (arm64, darwin) (push) Has been cancelled
Build and Release / Create Release (push) Has been cancelled
Build and Release / Build Binaries (arm64, linux) (push) Has been cancelled
Build and Release / Build Docker Image (push) Has been cancelled
docs: comprehensive testing guide covering all 5 phases
Updated testing guide now covers:

Phase 1: API Reliability
- Request ID tracing
- Rate limit headers
- Chunk checksum verification
- RFC 7807 error responses

Phase 2: V2 API
- V2 framework
- Scalar docs
- Batch operations
- NDJSON streaming
- AI context endpoints

Phase 3: Reliability Patterns
- Operation progress (SSE)
- Idempotency middleware
- Webhook retry
- Circuit breaker

Phase 4: SDK & CLI
- gitea-cli tool
- Go, Python, TypeScript, C#, Java SDKs

Phase 5: New Features
- Organization pinned repos
- Public members
- Gitea Pages (4 templates)
- Wiki V2 API

Also includes:
- Complete smoke test script
- Regression testing checklist
- Rollback plan

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:24:40 -05:00

25 KiB

Comprehensive Testing Guide for Gitea v1.26.0

All Features to Test

Phase Feature Risk Priority
1 Request ID Tracing Low Medium
1 Rate Limit Headers Low Medium
1 Chunk Checksum Verification Medium High
1 RFC 7807 Error Responses Low Medium
2 V2 API Framework Medium High
2 Structured Error Codes Low Medium
2 Scalar API Docs Low Low
2 Batch Operations Medium High
2 NDJSON Streaming Medium High
2 AI Context Endpoints Low Medium
3 Operation Progress (SSE) Medium High
3 Idempotency Middleware High Critical
3 Webhook Retry Medium High
3 Circuit Breaker Medium High
4 CLI Tool (gitea-cli) Low Medium
4 Go SDK Low Medium
4 Python SDK Low Medium
4 TypeScript SDK Low Medium
4 C# SDK Low Medium
4 Java SDK Low Medium
5 Organization Pinned Repos Low Medium
5 Organization Public Members Low Medium
5 Gitea Pages Medium High
5 Wiki V2 API Medium High

1. Test Environment Setup

Docker Test Instance

mkdir gitea-test && cd gitea-test

cat > docker-compose.yml << 'EOF'
version: "3"
services:
  gitea:
    image: gitea/gitea:1.26.0
    container_name: gitea-test
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=sqlite3
      - GITEA__server__ROOT_URL=http://localhost:3000/
    volumes:
      - ./gitea-data:/data
    ports:
      - "3000:3000"
      - "2222:22"
EOF

docker-compose up -d

2. Phase 1: API Reliability Enhancements

2.1 Request ID Tracing

# Test auto-generated request ID
curl -i http://localhost:3000/api/v1/version
# Should see: X-Request-ID: <short-uuid>

# Test custom request ID passed through
curl -i -H "X-Request-ID: my-custom-id-123" http://localhost:3000/api/v1/version
# Should see: X-Request-ID: my-custom-id-123

# Test request ID in error responses
curl -i http://localhost:3000/api/v1/repos/nonexistent/nonexistent
# Error JSON should contain request_id field

Checklist:

  • X-Request-ID header present in all responses
  • Custom X-Request-ID passed through unchanged
  • Request ID included in error response body
  • Request ID appears in server logs

2.2 Rate Limit Headers

# Check rate limit headers
curl -i -H "Authorization: token $TOKEN" http://localhost:3000/api/v1/user
# Should see:
# X-RateLimit-Limit: <configured limit>
# X-RateLimit-Remaining: <remaining>
# X-RateLimit-Reset: <unix timestamp>

Checklist:

  • Rate limit headers present on authenticated requests
  • Remaining count decrements
  • Reset timestamp is in the future

2.3 Chunk Checksum Verification

# Create a test file
echo "test content" > testfile.txt
CHECKSUM=$(sha256sum testfile.txt | cut -d' ' -f1)

# Upload with correct checksum (should succeed)
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "X-Chunk-Checksum: sha256=$CHECKSUM" \
  -F "file=@testfile.txt" \
  "http://localhost:3000/api/v1/repos/owner/repo/releases/1/assets"

# Upload with wrong checksum (should fail)
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "X-Chunk-Checksum: sha256=wrongchecksum123" \
  -F "file=@testfile.txt" \
  "http://localhost:3000/api/v1/repos/owner/repo/releases/1/assets"
# Should return 400 with checksum mismatch error

Checklist:

  • Upload succeeds with correct checksum
  • Upload fails with incorrect checksum
  • Upload succeeds without checksum header (optional)
  • Error message indicates checksum mismatch

2.4 RFC 7807 Error Responses

# Trigger a 404 error
curl -s http://localhost:3000/api/v1/repos/nonexistent/nonexistent | jq .

Expected Response:

{
  "type": "https://gitea.io/api/errors/not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "Repository not found",
  "instance": "/api/v1/repos/nonexistent/nonexistent",
  "request_id": "abc123",
  "message": "Repository not found",
  "url": "https://gitea.io/api/errors/not-found"
}

Checklist:

  • Error responses include type, title, status, detail
  • Legacy fields (message, url) still present for compatibility
  • request_id included in errors

3. Phase 2: V2 API with AI Features

3.1 V2 API Framework

# Test v2 version endpoint
curl http://localhost:3000/api/v2/version

# Test v2 user endpoint (requires auth)
curl -H "Authorization: token $TOKEN" http://localhost:3000/api/v2/user

Checklist:

  • V2 endpoints respond at /api/v2/
  • V1 endpoints still work at /api/v1/
  • Authentication works on v2

3.2 Scalar API Documentation

# Open in browser
open http://localhost:3000/api/v2/docs

# Fetch OpenAPI spec
curl http://localhost:3000/api/v2/swagger.json

Checklist:

  • Scalar docs page loads
  • All v2 endpoints documented
  • "Try it" functionality works

3.3 Batch Operations

# Batch get files
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "requests": [
      {"owner": "org", "repo": "repo1", "path": "README.md", "ref": "main"},
      {"owner": "org", "repo": "repo1", "path": "go.mod", "ref": "main"},
      {"owner": "org", "repo": "repo2", "path": "package.json", "ref": "main"}
    ]
  }' \
  http://localhost:3000/api/v2/batch/files

# Batch get repos
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "repos": [
      {"owner": "org", "repo": "repo1"},
      {"owner": "org", "repo": "repo2"},
      {"owner": "org", "repo": "repo3"}
    ]
  }' \
  http://localhost:3000/api/v2/batch/repos

Checklist:

  • Batch files returns multiple file contents
  • Batch repos returns multiple repo details
  • Partial failures handled gracefully (some succeed, some fail)
  • Performance better than individual requests

3.4 NDJSON Streaming

# Stream files
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/x-ndjson" \
  -d '{"owner": "org", "repo": "repo", "paths": ["file1.go", "file2.go"]}' \
  http://localhost:3000/api/v2/stream/files

# Stream commits
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/x-ndjson" \
  -d '{"owner": "org", "repo": "repo", "ref": "main", "limit": 100}' \
  http://localhost:3000/api/v2/stream/commits

# Stream issues
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/x-ndjson" \
  -d '{"owner": "org", "repo": "repo", "state": "open"}' \
  http://localhost:3000/api/v2/stream/issues

Checklist:

  • Responses are newline-delimited JSON
  • Each line is valid JSON
  • Streaming starts before all data is ready
  • Large datasets don't timeout

3.5 AI Context Endpoints

# Repository summary
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"owner": "org", "repo": "repo"}' \
  http://localhost:3000/api/v2/ai/repo/summary

# Navigation hints
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"owner": "org", "repo": "repo"}' \
  http://localhost:3000/api/v2/ai/repo/navigation

# Issue context
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"owner": "org", "repo": "repo", "issue_number": 1}' \
  http://localhost:3000/api/v2/ai/issue/context

Checklist:

  • Repo summary includes structure, languages, recent activity
  • Navigation includes important paths, file types
  • Issue context includes comments, labels, code references
  • AI hints provided (project type, suggested files)

4. Phase 3: Reliability Patterns

4.1 Operation Progress (SSE)

# Start a long operation that returns operation ID
OPERATION_ID=$(curl -X POST \
  -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/repos/owner/repo/mirror-sync" | jq -r '.operation_id')

# Subscribe to progress updates (SSE)
curl -N -H "Accept: text/event-stream" \
  "http://localhost:3000/api/v2/operations/$OPERATION_ID/progress"

# Check operation status
curl "http://localhost:3000/api/v2/operations/$OPERATION_ID"

# Cancel operation
curl -X DELETE "http://localhost:3000/api/v2/operations/$OPERATION_ID"

Checklist:

  • Operation ID returned from long-running endpoints
  • SSE stream provides real-time updates
  • Progress includes phase, percentage, ETA
  • Completed operations can be queried
  • Operations can be cancelled

4.2 Idempotency Middleware

# First request - should execute
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Idempotency-Key: unique-key-123" \
  -H "Content-Type: application/json" \
  -d '{"title": "Test Issue", "body": "Test body"}' \
  http://localhost:3000/api/v1/repos/owner/repo/issues

# Duplicate request - should return cached response
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Idempotency-Key: unique-key-123" \
  -H "Content-Type: application/json" \
  -d '{"title": "Test Issue", "body": "Test body"}' \
  http://localhost:3000/api/v1/repos/owner/repo/issues
# Should see header: Idempotency-Replayed: true
# Should NOT create duplicate issue

Checklist:

  • First request executes normally
  • Duplicate request returns cached response
  • Idempotency-Replayed: true header on cached responses
  • Different idempotency keys execute separately
  • Keys expire after 24 hours

4.3 Webhook Retry

# Configure a webhook to a non-responsive endpoint
# Trigger an event (push, issue create, etc.)
# Check webhook delivery logs

curl -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/repos/owner/repo/hooks/1/deliveries"

Checklist:

  • Failed deliveries are retried
  • Exponential backoff between retries
  • Max retries respected
  • Delivery attempts logged
  • Eventually marked as failed after max retries

4.4 Circuit Breaker

# This is internal - check via metrics or logs
# Simulate external service failure
# Verify circuit opens after threshold
# Verify circuit half-opens after timeout
# Verify circuit closes after success

Checklist:

  • Circuit opens after consecutive failures
  • Requests fail fast when circuit open
  • Circuit transitions to half-open after timeout
  • Successful request closes circuit
  • Circuit state visible in health endpoint

5. Phase 4: SDK and CLI Tools

5.1 CLI Tool (gitea-cli)

# Build CLI
cd cmd/gitea-cli && go build -o gitea-cli .

# Login
./gitea-cli auth login --server http://localhost:3000 --token $TOKEN

# Check auth status
./gitea-cli auth status

# Upload release asset
./gitea-cli upload release-asset \
  --owner myorg \
  --repo myrepo \
  --release-id 1 \
  --file ./large-file.zip

# List pending uploads
./gitea-cli upload list

# Resume interrupted upload
./gitea-cli upload resume --session-id <session-id>

# Logout
./gitea-cli auth logout

Checklist:

  • Login stores credentials securely
  • Upload shows progress bar
  • Chunked upload works for large files
  • Resume works after interruption
  • Checksum verification passes

5.2 Go SDK

package main

import (
    "fmt"
    gitea "code.gitea.io/gitea/sdk/go"
)

func main() {
    client := gitea.NewClient("http://localhost:3000", "your-token")

    // Get user
    user, err := client.GetCurrentUser()
    if err != nil {
        panic(err)
    }
    fmt.Printf("Logged in as: %s\n", user.UserName)

    // Upload file with progress
    err = client.UploadReleaseAsset(
        "owner", "repo", 1,
        "./large-file.zip",
        gitea.WithProgress(func(current, total int64) {
            fmt.Printf("\rProgress: %d/%d", current, total)
        }),
    )
}

Checklist:

  • Client initializes with token
  • Basic API calls work
  • Chunked upload works
  • Progress callback fires
  • Errors properly typed

5.3 Python SDK

from gitea_sdk import GiteaClient

client = GiteaClient("http://localhost:3000", token="your-token")

# Get user
user = client.get_current_user()
print(f"Logged in as: {user.username}")

# Upload with progress
def on_progress(current, total):
    print(f"\rProgress: {current}/{total}", end="")

client.upload_release_asset(
    owner="myorg",
    repo="myrepo",
    release_id=1,
    file_path="./large-file.zip",
    on_progress=on_progress
)

Checklist:

  • pip install works
  • Client connects with token
  • Basic API calls work
  • Type hints work in IDE
  • Chunked upload works

5.4 TypeScript SDK

import { GiteaClient } from '@gitea/sdk';

const client = new GiteaClient({
  baseUrl: 'http://localhost:3000',
  token: 'your-token'
});

// Get user
const user = await client.getCurrentUser();
console.log(`Logged in as: ${user.username}`);

// Upload with progress
await client.uploadReleaseAsset({
  owner: 'myorg',
  repo: 'myrepo',
  releaseId: 1,
  file: fs.createReadStream('./large-file.zip'),
  onProgress: (current, total) => {
    console.log(`Progress: ${current}/${total}`);
  }
});

Checklist:

  • npm install works
  • TypeScript types correct
  • Works in Node.js
  • Works in browser (where applicable)
  • Async/await works properly

5.5 C# SDK

using Gitea.SDK;

var client = new GiteaClient("http://localhost:3000", "your-token");

// Get user
var user = await client.GetCurrentUserAsync();
Console.WriteLine($"Logged in as: {user.UserName}");

// Upload with progress
await client.UploadReleaseAssetAsync(
    owner: "myorg",
    repo: "myrepo",
    releaseId: 1,
    filePath: "./large-file.zip",
    onProgress: (current, total) => {
        Console.WriteLine($"Progress: {current}/{total}");
    }
);

Checklist:

  • NuGet package installs
  • .NET 6+ compatible
  • Async methods work
  • Progress events fire
  • Proper disposal (IDisposable)

5.6 Java SDK

import io.gitea.sdk.GiteaClient;

GiteaClient client = new GiteaClient("http://localhost:3000", "your-token");

// Get user
User user = client.getCurrentUser();
System.out.println("Logged in as: " + user.getUserName());

// Upload with progress
client.uploadReleaseAsset(
    "myorg", "myrepo", 1,
    new File("./large-file.zip"),
    (current, total) -> {
        System.out.printf("Progress: %d/%d%n", current, total);
    }
);

Checklist:

  • Maven/Gradle dependency works
  • Java 11+ compatible
  • Fluent API works
  • Progress callback fires
  • Proper resource management

6. Phase 5: Organization Profiles

6.1 Pinned Repositories

# List pinned repos
curl -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/orgs/myorg/pinned"

# Pin a repository
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"repo_name": "my-repo"}' \
  "http://localhost:3000/api/v1/orgs/myorg/pinned"

# Create a pinned group
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Core Projects"}' \
  "http://localhost:3000/api/v1/orgs/myorg/pinned/groups"

# Add repo to group
curl -X PUT \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"group_id": 1}' \
  "http://localhost:3000/api/v1/orgs/myorg/pinned/my-repo"

# Reorder pinned repos
curl -X PUT \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"order": ["repo1", "repo2", "repo3"]}' \
  "http://localhost:3000/api/v1/orgs/myorg/pinned/reorder"

# Unpin repository
curl -X DELETE \
  -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/orgs/myorg/pinned/my-repo"

Web UI Checklist:

  • Pinned repos appear on org profile page
  • Groups are collapsible
  • Repo cards show stars, forks, language
  • Reordering works via drag-and-drop (if implemented)

6.2 Public Members

# List public members with roles
curl "http://localhost:3000/api/v1/orgs/myorg/public_members/roles"

# Make yourself public
curl -X PUT \
  -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/orgs/myorg/public_members/myusername"

# Remove public visibility
curl -X DELETE \
  -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/orgs/myorg/public_members/myusername"

Checklist:

  • Public members shown on org profile
  • Roles displayed (Owner, Admin, Member)
  • "and X more" overflow works
  • Opt-in/opt-out works

7. Phase 5: Gitea Pages

7.1 Basic Pages Setup

# Create test repo with landing.yaml
mkdir test-pages && cd test-pages
git init

cat > .gitea/landing.yaml << 'EOF'
enabled: true
template: simple

branding:
  primary_color: "#4a90d9"

hero:
  title: "My Project"
  tagline: "The best project ever"
EOF

cat > README.md << 'EOF'
# My Project

Welcome to my project!

## Features
- Feature 1
- Feature 2
EOF

git add -A && git commit -m "Initial commit"
git push origin main

7.2 Pages API

# Get pages config
curl -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/repos/owner/repo/pages"

# Enable pages
curl -X PUT \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true, "template": "simple"}' \
  "http://localhost:3000/api/v1/repos/owner/repo/pages"

# Add custom domain
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domain": "myproject.example.com"}' \
  "http://localhost:3000/api/v1/repos/owner/repo/pages/domains"

# Verify domain
curl -X POST \
  -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/repos/owner/repo/pages/domains/myproject.example.com/verify"

# Disable pages
curl -X DELETE \
  -H "Authorization: token $TOKEN" \
  "http://localhost:3000/api/v1/repos/owner/repo/pages"

7.3 Template Testing

Test each template by visiting http://localhost:3000/owner/repo/pages:

Simple Template:

  • Hero section displays
  • README content renders
  • Repo stats shown in footer

Documentation Template:

  • Sidebar navigation works
  • /docs folder content loads
  • Search works (if enabled)
  • "Edit this page" links work

Product Template:

  • Hero with background
  • Features grid displays
  • Screenshot section works
  • Releases section shows latest

Portfolio Template:

  • Gallery grid displays
  • Lightbox works on click
  • Captions display

8. Phase 5: Wiki V2 API

8.1 CRUD Operations

BASE="http://localhost:3000/api/v2/repos/owner/repo/wiki"

# List pages
curl -H "Authorization: token $TOKEN" "$BASE/pages"

# Get single page
curl -H "Authorization: token $TOKEN" "$BASE/pages/Home"

# Create page
curl -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Test-Page", "content": "# Test\n\nContent here."}' \
  "$BASE/pages"

# Update page
curl -X PUT \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content": "# Updated\n\nNew content."}' \
  "$BASE/pages/Test-Page"

# Rename page
curl -X PUT \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"rename_to": "New-Page-Name"}' \
  "$BASE/pages/Test-Page"

# Delete page
curl -X DELETE \
  -H "Authorization: token $TOKEN" \
  "$BASE/pages/New-Page-Name"

8.2 Search, Graph, Stats

# Search
curl -H "Authorization: token $TOKEN" "$BASE/search?q=installation"

# Link graph
curl -H "Authorization: token $TOKEN" "$BASE/graph"

# Statistics
curl -H "Authorization: token $TOKEN" "$BASE/stats"

# Page revisions
curl -H "Authorization: token $TOKEN" "$BASE/pages/Home/revisions"

8.3 Response Validation

Page Response Should Include:

  • content - raw markdown
  • content_html - rendered HTML
  • links_out - outgoing wiki links
  • links_in - incoming links
  • word_count - accurate count
  • last_commit - author, date, message

Stats Response Should Include:

  • total_pages
  • total_words
  • health.orphaned_pages
  • health.dead_links
  • health.outdated_pages
  • health.short_pages
  • top_linked

9. Regression Testing

Critical Existing Features

These MUST still work:

# Repository clone
git clone http://localhost:3000/owner/repo.git

# Push
git push origin main

# V1 API still works
curl http://localhost:3000/api/v1/version
curl -H "Authorization: token $TOKEN" http://localhost:3000/api/v1/user
curl http://localhost:3000/api/v1/repos/owner/repo

# Wiki V1 still works
curl http://localhost:3000/api/v1/repos/owner/repo/wiki/pages
curl http://localhost:3000/api/v1/repos/owner/repo/wiki/page/Home

# Issues
curl http://localhost:3000/api/v1/repos/owner/repo/issues

# Pull requests
curl http://localhost:3000/api/v1/repos/owner/repo/pulls

Checklist:

  • Git clone (HTTP)
  • Git clone (SSH)
  • Git push
  • Branch creation
  • Tag creation
  • Pull request creation
  • Pull request merge
  • Issue creation
  • Wiki (web UI)
  • Wiki (V1 API)
  • User login
  • Organization operations

10. Complete Smoke Test Script

#!/bin/bash
set -e

BASE="${GITEA_URL:-http://localhost:3000}"
TOKEN="${GITEA_TOKEN:-your-token}"
OWNER="${TEST_OWNER:-testorg}"
REPO="${TEST_REPO:-testrepo}"

RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'

pass() { echo -e "${GREEN}${NC} $1"; }
fail() { echo -e "${RED}${NC} $1"; FAILED=1; }

test_endpoint() {
    local name=$1
    local method=${2:-GET}
    local url=$3
    local data=$4

    if [ -n "$data" ]; then
        response=$(curl -sf -X $method -H "Authorization: token $TOKEN" \
            -H "Content-Type: application/json" -d "$data" "$url" 2>/dev/null) && pass "$name" || fail "$name"
    else
        response=$(curl -sf -X $method -H "Authorization: token $TOKEN" "$url" 2>/dev/null) && pass "$name" || fail "$name"
    fi
}

echo "=== Gitea v1.26.0 Comprehensive Smoke Tests ==="
echo ""

echo "--- Phase 1: API Reliability ---"
test_endpoint "Version endpoint" GET "$BASE/api/v1/version"
test_endpoint "Request ID header" GET "$BASE/api/v1/version"

echo ""
echo "--- Phase 2: V2 API ---"
test_endpoint "V2 Version" GET "$BASE/api/v2/version"
test_endpoint "V2 User" GET "$BASE/api/v2/user"
test_endpoint "V2 Docs" GET "$BASE/api/v2/docs"
test_endpoint "V2 Batch Files" POST "$BASE/api/v2/batch/files" '{"requests":[]}'
test_endpoint "V2 AI Repo Summary" POST "$BASE/api/v2/ai/repo/summary" "{\"owner\":\"$OWNER\",\"repo\":\"$REPO\"}"

echo ""
echo "--- Phase 3: Reliability ---"
test_endpoint "Health Check" GET "$BASE/api/v2/health"

echo ""
echo "--- Phase 5: Org Profiles ---"
test_endpoint "Org Pinned Repos" GET "$BASE/api/v1/orgs/$OWNER/pinned"
test_endpoint "Org Public Members" GET "$BASE/api/v1/orgs/$OWNER/public_members/roles"

echo ""
echo "--- Phase 5: Pages ---"
test_endpoint "Pages Config" GET "$BASE/api/v1/repos/$OWNER/$REPO/pages"

echo ""
echo "--- Phase 5: Wiki V2 ---"
test_endpoint "Wiki List Pages" GET "$BASE/api/v2/repos/$OWNER/$REPO/wiki/pages"
test_endpoint "Wiki Search" GET "$BASE/api/v2/repos/$OWNER/$REPO/wiki/search?q=test"
test_endpoint "Wiki Graph" GET "$BASE/api/v2/repos/$OWNER/$REPO/wiki/graph"
test_endpoint "Wiki Stats" GET "$BASE/api/v2/repos/$OWNER/$REPO/wiki/stats"

echo ""
echo "--- Regression: V1 API ---"
test_endpoint "V1 User" GET "$BASE/api/v1/user"
test_endpoint "V1 Repos" GET "$BASE/api/v1/repos/$OWNER/$REPO"
test_endpoint "V1 Wiki Pages" GET "$BASE/api/v1/repos/$OWNER/$REPO/wiki/pages"

echo ""
if [ -z "$FAILED" ]; then
    echo -e "${GREEN}All tests passed!${NC}"
    exit 0
else
    echo -e "${RED}Some tests failed!${NC}"
    exit 1
fi

Save as smoke-test.sh and run:

chmod +x smoke-test.sh
GITEA_URL=http://localhost:3000 GITEA_TOKEN=your-token ./smoke-test.sh

11. Rollback Plan

If any issues are found:

# 1. Stop current version
docker-compose down

# 2. Restore previous version
docker pull gitea/gitea:1.25.3

# 3. Update docker-compose.yml to use 1.25.3

# 4. Start previous version
docker-compose up -d

Safe to rollback because:

  • New tables (wiki_index, pages_, org_pinned_) are ignored by old version
  • No existing tables were modified
  • V1 API unchanged
  • No data migration required

Summary

Testing Priority:

  1. Critical: Idempotency, chunked uploads, V1 API regression
  2. High: V2 batch/streaming, wiki V2 CRUD, pages rendering
  3. Medium: SDKs, CLI, org profiles, operation progress
  4. Low: Scalar docs, AI context endpoints

Recommended Testing Time:

  • Automated tests: 30 minutes
  • Manual testing: 2-4 hours
  • Staging soak test: 24-48 hours
  • Total: 2-3 days before production