adding script to programmatically add issues to the forgejo project kanban

This commit is contained in:
lila 2026-04-16 14:43:59 +02:00
parent fe0315938a
commit a7be7152cc

280
scripts/create-issues.sh Normal file
View file

@ -0,0 +1,280 @@
#!/bin/bash
# Forgejo batch issue creator for lila
# Usage: FORGEJO_TOKEN=your_token ./create-issues.sh
FORGEJO_URL="https://git.lilastudy.com"
OWNER="forgejo-lila"
REPO="lila"
TOKEN="${FORGEJO_TOKEN:?Set FORGEJO_TOKEN environment variable}"
API="${FORGEJO_URL}/api/v1/repos/${OWNER}/${REPO}"
# Helper: create a label (ignores if already exists)
create_label() {
local name="$1" color="$2" description="$3"
curl -s -X POST "${API}/labels" \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"name\":\"${name}\",\"color\":\"${color}\",\"description\":\"${description}\"}" > /dev/null
echo "Label: ${name}"
}
# Helper: create an issue with labels
create_issue() {
local title="$1" body="$2"
shift 2
local labels="$*"
# Build labels JSON array
local label_ids=""
for label in $labels; do
local id
id=$(curl -s "${API}/labels" \
-H "Authorization: token ${TOKEN}" | \
python3 -c "import sys,json; [print(l['id']) for l in json.load(sys.stdin) if l['name']=='${label}']")
if [ -n "$label_ids" ]; then
label_ids="${label_ids},${id}"
else
label_ids="${id}"
fi
done
curl -s -X POST "${API}/issues" \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"title\":$(echo "$title" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read().strip()))'),\"body\":$(echo "$body" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read().strip()))'),\"labels\":[${label_ids}]}" > /dev/null
echo "Issue: ${title}"
}
echo "=== Creating labels ==="
create_label "feature" "#0075ca" "New user-facing functionality"
create_label "infra" "#e4e669" "Infrastructure, deployment, DevOps"
create_label "debt" "#d876e3" "Technical cleanup, refactoring"
create_label "security" "#b60205" "Security improvements"
create_label "ux" "#1d76db" "User experience, accessibility, polish"
create_label "multiplayer" "#0e8a16" "Multiplayer lobby and game features"
echo ""
echo "=== Creating issues ==="
# ── feature ──
create_issue \
"Add guest/try-now option — play without account" \
"Allow users to play a quiz without signing in so they can see what the app offers before creating an account. Make auth middleware optional on game routes, add a 'Try without account' button on the login/landing page." \
feature
create_issue \
"Add Apple login provider" \
"Add Apple as a social login option via Better Auth. Requires Apple Developer account and Sign in with Apple configuration." \
feature
create_issue \
"Add email+password login" \
"Add traditional email and password authentication as an alternative to social login. Configure via Better Auth." \
feature
create_issue \
"User stats endpoint + profile page" \
"Add GET /users/me/stats endpoint returning games played, score history, etc. Build a frontend profile page displaying the stats." \
feature
# ── infra ──
create_issue \
"Google OAuth app verification and publishing" \
"Currently only test users can log in via Google. Publish the OAuth consent screen so any Google user can sign in. Requires branding verification through Google Cloud Console." \
infra
create_issue \
"Set up Docker credential helper on dev laptop" \
"Docker credentials are stored unencrypted in ~/.docker/config.json. Set up a credential helper to store them securely. See https://docs.docker.com/go/credential-store/" \
infra
create_issue \
"VPS monitoring and logging" \
"Set up monitoring and centralized logging on the VPS. Options: chkrootkit/rkhunter for security, logwatch/monit for daily summaries, uptime monitoring for service health." \
infra
create_issue \
"Move to offsite backup storage" \
"Currently database backups live on the same VPS. Add offsite copies to Hetzner Object Storage or similar S3-compatible service to protect against VPS failure." \
infra
create_issue \
"Replace in-memory game session store with Valkey" \
"Add Valkey container to the production Docker stack. Implement ValkeyGameSessionStore using the existing GameSessionStore interface. Required before multiplayer." \
infra
create_issue \
"Modern env management approach" \
"Evaluate replacing .env files with a more robust approach (e.g. dotenvx, infisical, or similar). Current setup works but .env files are error-prone and not versioned." \
infra
create_issue \
"Pin dependencies in package.json files" \
"Pin all dependency versions in package.json files to exact versions to prevent unexpected updates from breaking builds." \
infra
# ── debt ──
create_issue \
"Rethink organization of datafiles and wordlists" \
"The current layout of data-sources/, scripts/datafiles/, scripts/data-sources/, and packages/db/src/data/ is confusing with overlapping content. Consolidate into a clear structure." \
debt
create_issue \
"Resolve eslint peer dependency warning" \
"eslint-plugin-react-hooks 7.0.1 expects eslint ^3.0.0-^9.0.0 but found 10.0.3. Resolve the peer dependency mismatch." \
debt
# ── security ──
create_issue \
"Rate limiting on API endpoints" \
"Add rate limiting to prevent abuse. At minimum: auth endpoints (brute force prevention), game endpoints (spam prevention). Consider express-rate-limit or similar." \
security
# ── ux ──
create_issue \
"404/redirect handling for unknown routes and subdomains" \
"Unknown routes return raw errors. Add a catch-all route on the frontend for client-side 404s. Consider Caddy fallback for unrecognized subdomains." \
ux
create_issue \
"React error boundaries" \
"Add error boundaries to catch and display runtime errors gracefully instead of crashing the entire app." \
ux
create_issue \
"Accessibility pass" \
"Keyboard navigation for quiz buttons, ARIA labels on interactive elements, focus management during quiz flow." \
ux
create_issue \
"Favicon, page titles, Open Graph meta" \
"Add favicon, set proper page titles per route, add Open Graph meta tags for link previews when sharing." \
ux
# ── multiplayer ──
create_issue \
"Drizzle schema: lobbies, lobby_players + migration" \
"Create lobbies table (id, code, host_user_id, status, is_private, game_mode, settings, created_at) and lobby_players table (lobby_id, user_id, score, joined_at). Run migration. See game-modes.md for game_mode values." \
multiplayer
create_issue \
"REST endpoints: POST /lobbies, POST /lobbies/:code/join" \
"Create lobby (generates short code, sets host) and join lobby (validates code, adds player, enforces max limit)." \
multiplayer
create_issue \
"LobbyService: create lobby, join lobby, enforce player limit" \
"Service layer for lobby management. Generate human-readable codes, validate join requests, track lobby state. Public lobbies are browsable, private lobbies require code." \
multiplayer
create_issue \
"WebSocket server: attach ws upgrade to Express" \
"Attach ws library upgrade handler to the existing Express HTTP server. Handle connection lifecycle." \
multiplayer
create_issue \
"WS auth middleware: validate session on upgrade" \
"Validate Better Auth session on WebSocket upgrade request. Reject unauthenticated connections." \
multiplayer
create_issue \
"WS message router: dispatch by type" \
"Route incoming WebSocket messages by their type field to the appropriate handler. Use Zod discriminated union for type safety." \
multiplayer
create_issue \
"Lobby join/leave handlers + broadcast lobby state" \
"Handle lobby:join and lobby:leave WebSocket events. Broadcast updated player list to all connected players in the lobby." \
multiplayer
create_issue \
"Lobby state in Valkey (ephemeral) + PostgreSQL (durable)" \
"Store live lobby state (connected players, current question, timer) in Valkey. Store durable records (who played, final scores) in PostgreSQL." \
multiplayer
create_issue \
"WS event Zod schemas in packages/shared" \
"Define all WebSocket message types as Zod discriminated unions in packages/shared. Covers lobby events (join, leave, start) and game events (question, answer, result, finished)." \
multiplayer
create_issue \
"Frontend: lobby browser + create/join lobby" \
"Lobby list showing public open lobbies. Create lobby form (game mode, public/private). Join-by-code input for private lobbies." \
multiplayer
create_issue \
"Frontend: lobby view (player list, code, start game)" \
"Show lobby code, connected players, game mode. Host sees Start Game button. Players see waiting state. Real-time updates via WebSocket." \
multiplayer
create_issue \
"Frontend: WS client singleton with reconnect" \
"WebSocket client that maintains a single connection, handles reconnection on disconnect, and dispatches incoming messages to the appropriate state handlers." \
multiplayer
create_issue \
"GameService: question sequence + server timer" \
"Generate question sequence for a lobby game. Enforce per-question timer (e.g. 15s). Timer logic varies by game mode — see game-modes.md." \
multiplayer
create_issue \
"lobby:start WS handler — broadcast first question" \
"When host starts the game, generate questions, change lobby status to in_progress, broadcast first question to all players." \
multiplayer
create_issue \
"game:answer WS handler — collect answers" \
"Receive player answers via WebSocket. Track who has answered. Behavior varies by game mode (simultaneous vs turn-based vs buzzer)." \
multiplayer
create_issue \
"Answer evaluation + broadcast results" \
"On all-answered or timeout: evaluate answers, calculate scores, broadcast game:answer_result to all players. Then send next question or end game." \
multiplayer
create_issue \
"Game finished: broadcast results, update DB" \
"After final round: broadcast game:finished with final scores and winner. Write game results to PostgreSQL (transactional). Change lobby status to finished." \
multiplayer
create_issue \
"Frontend: multiplayer game route" \
"Route for active multiplayer games. Receives questions and results via WebSocket. Reuses QuestionCard and OptionButton components." \
multiplayer
create_issue \
"Frontend: countdown timer component" \
"Visual countdown timer synchronized with server timer. Shows remaining seconds per question." \
multiplayer
create_issue \
"Frontend: ScoreBoard component (live per-player scores)" \
"Displays live scores for all players during a multiplayer game. Updates in real-time via WebSocket." \
multiplayer
create_issue \
"Frontend: GameFinished screen" \
"Winner highlight, final scores, play again option. Returns to lobby on play again." \
multiplayer
create_issue \
"Multiplayer GameService unit tests" \
"Unit tests for round evaluation, scoring, tie-breaking, timeout handling across different game modes." \
multiplayer
create_issue \
"Graceful WS reconnect with exponential back-off" \
"Handle WebSocket disconnections gracefully. Reconnect with exponential back-off. Restore game state on reconnection if game is still in progress." \
multiplayer
echo ""
echo "=== Done ==="