chore: remove sensitive files for GitHub mirror

This commit is contained in:
2025-10-29 11:29:50 +00:00
parent d2e97567a9
commit 81416737e8
26 changed files with 0 additions and 2811 deletions
File diff suppressed because it is too large Load Diff
-114
View File
@@ -1,114 +0,0 @@
kind: pipeline
type: docker
name: default
steps:
# Build Backend Docker Image
- name: build-backend
image: plugins/docker
settings:
repo: registry.local.nothaft.cloud/picpeak-backend
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8}
- ${DRONE_BRANCH}-latest
dockerfile: backend/Dockerfile
context: backend/
registry: registry.local.nothaft.cloud
build_args:
- VERSION=${DRONE_TAG:-dev}
# Build Frontend Docker Image
- name: build-frontend
image: plugins/docker
settings:
repo: registry.local.nothaft.cloud/picpeak-frontend
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8}
- ${DRONE_BRANCH}-latest
dockerfile: frontend/Dockerfile
context: frontend/
registry: registry.local.nothaft.cloud
build_args:
- VERSION=${DRONE_TAG:-dev}
- VITE_API_URL=${VITE_API_URL:-/api}
trigger:
branch:
- main
- develop
event:
- push
- pull_request
---
kind: pipeline
type: docker
name: release
steps:
# Build Backend Release
- name: build-backend-release
image: plugins/docker
settings:
repo: registry.local.nothaft.cloud/picpeak-backend
tags:
- ${DRONE_TAG}
- latest
dockerfile: backend/Dockerfile
context: backend/
registry: registry.local.nothaft.cloud
# Build Frontend Release
- name: build-frontend-release
image: plugins/docker
settings:
repo: registry.local.nothaft.cloud/picpeak-frontend
tags:
- ${DRONE_TAG}
- latest
dockerfile: frontend/Dockerfile
context: frontend/
registry: registry.local.nothaft.cloud
# -------- NEW: Publish Docker images to GitHub Container Registry --------
- name: push-backend-ghcr
image: plugins/docker
settings:
repo: ghcr.io/the-luap/picpeak-backend
tags:
- ${DRONE_TAG}
- latest
dockerfile: backend/Dockerfile
context: backend/
registry: ghcr.io
username:
from_secret: GITHUB_USERNAME
password:
from_secret: GITHUB_TOKEN
build_args:
- VERSION=${DRONE_TAG}
- name: push-frontend-ghcr
image: plugins/docker
settings:
repo: ghcr.io/the-luap/picpeak-frontend
tags:
- ${DRONE_TAG}
- latest
dockerfile: frontend/Dockerfile
context: frontend/
registry: ghcr.io
username:
from_secret: GITHUB_USERNAME
password:
from_secret: GITHUB_TOKEN
build_args:
- VERSION=${DRONE_TAG}
- VITE_API_URL=${VITE_API_URL:-/api}
trigger:
event:
- tag
-132
View File
@@ -1,132 +0,0 @@
name: Mirror to GitHub
on:
workflow_dispatch: # Allow manual triggering only
jobs:
mirror:
runs-on: ubuntu-latest
# Note: For GitHub fine-grained tokens, ensure the token has:
# - Repository access to the-luap/picpeak
# - Repository permissions: Contents (Read and Write), Metadata (Read)
# For classic tokens: repo scope is sufficient
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0 # Full history for proper mirroring
- name: Setup Git
run: |
git config --global user.name "the-luap"
git config --global user.email "paul-nothaft@hotmail.de"
- name: Remove sensitive files and directories
run: |
echo "Current files before cleanup:"
ls -la | head -10 || true
echo "..."
# Remove sensitive files/directories if they exist
echo "Removing sensitive files..."
rm -rf .gitea/ || true
rm -rf scripts/install-gitea-runner.sh || true
rm -rf .drone* || true
rm -rf photo-sharing-prd.md || true
rm -rf CLAUDE.md || true
rm -rf storage/ || true
rm -rf events/ || true
rm -rf .playwright-mcp/
rm -rf .swarm || true
rm -rf .claude-flow || true
echo "Sensitive files removal completed"
# Add and commit the cleanup if there are changes
git add -A
if ! git diff --cached --quiet; then
git commit -m "chore: remove sensitive files for GitHub mirror"
echo "✅ Committed cleanup of sensitive files"
else
echo "✅ No sensitive files to remove"
fi
echo "Final file structure (top level):"
ls -la | head -10 || true
- name: Check GitHub token
env:
GITHUBTOKEN: ${{ secrets.GITHUBTOKEN }}
run: |
if [ -z "$GITHUBTOKEN" ]; then
echo "ERROR: GITHUBTOKEN secret is not set!"
echo "Please add a GitHub Personal Access Token as a secret named GITHUBTOKEN"
echo ""
echo "For fine-grained tokens:"
echo " - Go to GitHub Settings > Developer settings > Personal access tokens > Fine-grained tokens"
echo " - Create token with repository access to the-luap/picpeak"
echo " - Grant permissions: Contents (Read and Write), Metadata (Read)"
echo ""
echo "For classic tokens:"
echo " - Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)"
echo " - Create token with 'repo' scope"
exit 1
else
echo "✅ GitHub token is available (length: ${#GITHUBTOKEN})"
# Try to detect token type (fine-grained tokens are typically longer)
if [ ${#GITHUBTOKEN} -gt 80 ]; then
echo "📌 Token appears to be a fine-grained personal access token"
else
echo "📌 Token appears to be a classic personal access token"
fi
fi
- name: Push to GitHub
env:
GITHUBTOKEN: ${{ secrets.GITHUBTOKEN }}
GIT_TRACE: 1 # Enable Git trace for debugging if needed
run: |
# Remove existing github remote if it exists
git remote remove github || true
# Configure Git to use the token for authentication
# This method works for both classic and fine-grained tokens
git config --global url."https://the-luap:${GITHUBTOKEN}@github.com/".insteadOf "https://github.com/"
# Add GitHub remote (clean URL without credentials)
git remote add github https://github.com/the-luap/picpeak.git
# Verify remote was added
echo "GitHub remote configuration:"
git remote -v
# Push to GitHub main branch with error handling
echo "Pushing to GitHub..."
if git push github main --force 2>&1; then
echo "✅ Push to GitHub completed successfully!"
else
echo "❌ Push to GitHub failed!"
echo ""
echo "Common issues and solutions:"
echo "1. Token permissions: Ensure your token has 'Contents: write' permission"
echo "2. Token expiration: Check if your token has expired"
echo "3. Repository access: Verify the token has access to the-luap/picpeak repository"
echo ""
echo "For fine-grained tokens, required permissions:"
echo " - Repository access: the-luap/picpeak"
echo " - Repository permissions: Contents (Read and Write), Metadata (Read)"
echo ""
echo "For classic tokens, required scope: 'repo'"
exit 1
fi
# Clean up the git config after push
git config --global --unset url."https://the-luap:${GITHUBTOKEN}@github.com/".insteadOf
- name: Workflow completed
run: |
echo "✅ Mirror to GitHub workflow completed successfully!"
echo "📊 Repository mirrored to: https://github.com/the-luap/picpeak"
echo "🔒 Sensitive files have been removed from the mirror"
-52
View File
@@ -1,52 +0,0 @@
name: Test and Lint
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
backend-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install backend dependencies
working-directory: ./backend
run: npm ci
- name: Run backend linting
working-directory: ./backend
run: npm run lint || true # Continue on lint errors for now
- name: Run backend tests
working-directory: ./backend
run: npm test || true # Continue on test failures for now
frontend-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install frontend dependencies
working-directory: ./frontend
run: npm ci --legacy-peer-deps
- name: Run frontend linting
working-directory: ./frontend
run: npm run lint || true # Continue on lint errors for now
- name: Build frontend
working-directory: ./frontend
run: npm run build
-269
View File
@@ -1,269 +0,0 @@
name: Version and Release
on:
workflow_dispatch:
jobs:
version-bump:
runs-on: ubuntu-latest
outputs:
new_version: ${{ steps.version.outputs.new_version }}
version_changed: ${{ steps.version.outputs.version_changed }}
component_changed: ${{ steps.version.outputs.component_changed }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.GITEA_TOKEN || github.token }}
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Configure Git
run: |
git config --global user.name 'Gitea Actions Bot'
git config --global user.email 'actions@gitea.local'
- name: Detect changes and bump version
id: version
run: |
set -e # Exit on error
echo "=== Debug Info ==="
echo "GitHub event before: ${{ github.event.before }}"
echo "GitHub SHA: ${{ github.sha }}"
echo "Current directory: $(pwd)"
echo "Git log (last 5): $(git log --oneline -5)"
# Get the commit range for changed files
if [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ] && [ "${{ github.event.before }}" != "" ]; then
COMMIT_RANGE="${{ github.event.before }}..${{ github.sha }}"
echo "Using commit range: $COMMIT_RANGE"
CHANGED_FILES=$(git diff --name-only $COMMIT_RANGE || echo "")
else
# First commit or no previous commit, check against HEAD~1 if it exists
if git rev-parse HEAD~1 >/dev/null 2>&1; then
COMMIT_RANGE="HEAD~1..HEAD"
echo "Using commit range: $COMMIT_RANGE"
CHANGED_FILES=$(git diff --name-only $COMMIT_RANGE || echo "")
else
echo "First commit detected, checking all files"
CHANGED_FILES=$(git ls-files)
fi
fi
echo "Changed files:"
echo "$CHANGED_FILES"
# Check what changed (using echo to pipe to grep to avoid grep exit codes)
BACKEND_CHANGED=$(echo "$CHANGED_FILES" | grep -c '^backend/' || echo "0")
FRONTEND_CHANGED=$(echo "$CHANGED_FILES" | grep -c '^frontend/' || echo "0")
ROOT_CHANGED=$(echo "$CHANGED_FILES" | grep -c -E '^(package\.json|docker-compose|Dockerfile|scripts/)' || echo "0")
echo "Backend files changed: $BACKEND_CHANGED"
echo "Frontend files changed: $FRONTEND_CHANGED"
echo "Root files changed: $ROOT_CHANGED"
# Get current versions
BACKEND_VERSION=$(node -p "require('./backend/package.json').version" 2>/dev/null || echo "1.1.0")
FRONTEND_VERSION=$(node -p "require('./frontend/package.json').version" 2>/dev/null || echo "1.1.0")
echo "Current backend version: $BACKEND_VERSION"
echo "Current frontend version: $FRONTEND_VERSION"
# Determine what to update based on changes
BACKEND_UPDATE=false
FRONTEND_UPDATE=false
COMPONENT_CHANGED="none"
if [ "$ROOT_CHANGED" -gt 0 ]; then
# Root changes affect both components
BACKEND_UPDATE=true
FRONTEND_UPDATE=true
COMPONENT_CHANGED="both"
SOURCE_VERSION=$BACKEND_VERSION
echo "Root changes detected - updating both components"
elif [ "$BACKEND_CHANGED" -gt 0 ] && [ "$FRONTEND_CHANGED" -gt 0 ]; then
# Both components changed
BACKEND_UPDATE=true
FRONTEND_UPDATE=true
COMPONENT_CHANGED="both"
# Use the higher version as source
if [ "$(printf '%s\n' "$BACKEND_VERSION" "$FRONTEND_VERSION" | sort -V | tail -n1)" = "$BACKEND_VERSION" ]; then
SOURCE_VERSION=$BACKEND_VERSION
else
SOURCE_VERSION=$FRONTEND_VERSION
fi
echo "Both backend and frontend changed - updating both"
elif [ "$BACKEND_CHANGED" -gt 0 ]; then
# Only backend changed
BACKEND_UPDATE=true
COMPONENT_CHANGED="backend"
SOURCE_VERSION=$BACKEND_VERSION
echo "Only backend changed - updating backend"
elif [ "$FRONTEND_CHANGED" -gt 0 ]; then
# Only frontend changed
FRONTEND_UPDATE=true
COMPONENT_CHANGED="frontend"
SOURCE_VERSION=$FRONTEND_VERSION
echo "Only frontend changed - updating frontend"
else
echo "No relevant changes detected"
echo "version_changed=false" >> $GITHUB_OUTPUT
echo "component_changed=none" >> $GITHUB_OUTPUT
echo "new_version=" >> $GITHUB_OUTPUT
exit 0
fi
echo "Component changed: $COMPONENT_CHANGED"
echo "Source version: $SOURCE_VERSION"
echo "Backend update: $BACKEND_UPDATE"
echo "Frontend update: $FRONTEND_UPDATE"
# Calculate new version
IFS='.' read -r -a version_parts <<< "$SOURCE_VERSION"
MAJOR="${version_parts[0]}"
MINOR="${version_parts[1]}"
PATCH="${version_parts[2]}"
# Increment patch version and ensure tag uniqueness
git fetch --tags --quiet || true
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH"
while git rev-parse "v${NEW_VERSION}" >/dev/null 2>&1; do
echo "Tag v${NEW_VERSION} already exists, bumping patch version again"
NEW_PATCH=$((NEW_PATCH + 1))
NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH"
done
echo "New version: $NEW_VERSION"
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "component_changed=$COMPONENT_CHANGED" >> $GITHUB_OUTPUT
# Update versions in package.json files
if [ "$BACKEND_UPDATE" = true ]; then
echo "Updating backend version to $NEW_VERSION"
cd backend && npm version $NEW_VERSION --no-git-tag-version
cd ..
fi
if [ "$FRONTEND_UPDATE" = true ]; then
echo "Updating frontend version to $NEW_VERSION"
cd frontend && npm version $NEW_VERSION --no-git-tag-version
cd ..
fi
# Check if there are changes to commit
if [[ -n $(git status --porcelain) ]]; then
echo "version_changed=true" >> $GITHUB_OUTPUT
else
echo "version_changed=false" >> $GITHUB_OUTPUT
fi
- name: Commit version bump
if: steps.version.outputs.version_changed == 'true'
run: |
set -e # Exit on any error
# First, ensure we have the latest changes
echo "Fetching latest changes..."
git fetch origin main
# Check if we're behind and need to update
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/main)
if [ "$LOCAL" != "$REMOTE" ]; then
echo "Local is behind remote, pulling changes..."
git pull origin main --no-rebase
fi
COMPONENT="${{ steps.version.outputs.component_changed }}"
if [ "$COMPONENT" = "both" ]; then
git add backend/package.json backend/package-lock.json frontend/package.json frontend/package-lock.json
git commit -m "chore: bump version to ${{ steps.version.outputs.new_version }} (backend + frontend)"
elif [ "$COMPONENT" = "backend" ]; then
git add backend/package.json backend/package-lock.json
git commit -m "chore: bump backend version to ${{ steps.version.outputs.new_version }}"
elif [ "$COMPONENT" = "frontend" ]; then
git add frontend/package.json frontend/package-lock.json
git commit -m "chore: bump frontend version to ${{ steps.version.outputs.new_version }}"
fi
# Pull latest changes before pushing to avoid conflicts
echo "Pulling latest changes from origin/main..."
if ! git pull --rebase origin main; then
echo "Rebase failed, attempting to resolve..."
# If rebase fails, abort and try a regular merge
git rebase --abort || true
git pull origin main --no-rebase
fi
# Push the changes with retry logic
echo "Pushing version bump..."
PUSH_SUCCESS=false
for i in 1 2 3; do
echo "Push attempt $i of 3..."
# Try to push
if git push origin main 2>&1; then
echo "Successfully pushed version bump on attempt $i"
PUSH_SUCCESS=true
break
else
echo "Push failed on attempt $i"
if [ $i -lt 3 ]; then
echo "Waiting 5 seconds before retry..."
sleep 5
echo "Pulling latest changes..."
git fetch origin main
# Try rebase first, fall back to merge
if ! git rebase origin/main; then
echo "Rebase failed, trying merge..."
git rebase --abort 2>/dev/null || true
git pull origin main --no-rebase
fi
fi
fi
done
if [ "$PUSH_SUCCESS" = "false" ]; then
echo "ERROR: Failed to push after 3 attempts"
exit 1
fi
- name: Create Git tag
if: steps.version.outputs.version_changed == 'true'
run: |
COMPONENT="${{ steps.version.outputs.component_changed }}"
if [ "$COMPONENT" = "both" ]; then
TAG_MESSAGE="Release v${{ steps.version.outputs.new_version }} (backend + frontend)"
elif [ "$COMPONENT" = "backend" ]; then
TAG_MESSAGE="Release v${{ steps.version.outputs.new_version }} (backend)"
elif [ "$COMPONENT" = "frontend" ]; then
TAG_MESSAGE="Release v${{ steps.version.outputs.new_version }} (frontend)"
fi
git tag -a "v${{ steps.version.outputs.new_version }}" -m "$TAG_MESSAGE"
git push origin "v${{ steps.version.outputs.new_version }}"
trigger-drone:
needs: version-bump
if: needs.version-bump.outputs.version_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Trigger Drone Build
run: |
echo "Version bumped to ${{ needs.version-bump.outputs.new_version }}"
echo "Component(s) changed: ${{ needs.version-bump.outputs.component_changed }}"
echo "Drone will automatically trigger on the new tag"
# Drone CI will automatically trigger on the tag push event
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
-386
View File
@@ -1,386 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Product Overview
A secure photo sharing platform designed for weddings and events, enabling photographers to share time-limited, password-protected galleries. The platform features automatic expiration, archiving, and a scrappbook.de-inspired modern, minimalist UI.
## Architecture Overview
- **Backend**: Node.js/Express API with SQLite/PostgreSQL, file-based photo storage
- **Frontend**: React SPA with scrappbook.de-style design (requires implementation)
- **Storage**: File-based with active/archived separation
- **Services**: Background workers for email, archiving, file watching, and expiration monitoring
- **Analytics**: Umami integration for engagement tracking
## Essential Commands
### Backend Development
```bash
cd backend
npm install # Install dependencies
npm run migrate # Initialize database schema
npm run dev # Start with hot-reload (port 3001)
npm test # Run Jest tests
npm run lint # ESLint checks
```
### Running a Single Test
```bash
cd backend
npm test -- path/to/test.test.js
npm test -- --testNamePattern="test name"
```
### Production Deployment
See [DEPLOYMENT_GUIDE.md](./DEPLOYMENT_GUIDE.md) for comprehensive deployment instructions including:
- Docker Compose deployment
- PM2 deployment
- Manual installation
- Non-nginx deployment options
- SSL/HTTPS setup
- Troubleshooting guide
**⚠️ CRITICAL PRODUCTION NOTICE:**
- Production runs on a SEPARATE SERVER - never assume local changes affect production
- ALWAYS request production server details before any troubleshooting
- NO trial-and-error approaches in production - data loss is unacceptable
- Every change must be thoroughly analyzed and tested locally first
## Key Product Requirements (from PRD)
### Core Features
1. **File-Based System**: Drop photos in folders → automatic gallery creation
2. **Automatic Expiration**: Default 30 days, with 7-day warning emails
3. **Password Protection**: Secure access with customizable passwords
4. **Automatic Archiving**: ZIP compression and storage after expiration
5. **Email Notifications**: Creation, warning, and expiration notifications
6. **Analytics**: Umami tracking for views, downloads, and engagement
### Folder Structure
```
/events/
├── active/
│ ├── wedding-smith-jones-2024-06-15/
│ │ ├── collages/
│ │ └── individual/
│ └── birthday-emma-2024-07-20/
└── archived/
└── wedding-smith-jones-2024-06-15.zip
```
## Frontend Implementation Requirements
### Design Style (scrappbook.de-inspired)
- **Color Palette**: Primary green (#5C8762), neutral backgrounds
- **Typography**: Clean, modern sans-serif (Noto Sans or similar)
- **Layout**: Minimalist, modular sections with grid-based photo displays
- **Aesthetic**: Professional yet approachable, photographer-focused
### Key Frontend Components to Build
1. **Landing Page**: Password entry with event preview
2. **Gallery View**:
- Responsive photo grid with lazy loading
- Toggle between collages/individual photos
- Prominent expiration banner
- Download urgency indicators
3. **Photo Lightbox**: Full-screen viewing with zoom
4. **Mobile-First**: Responsive design with touch gestures
5. **Personalization**: Dynamic theming per event type
### User Experience Priorities
- Clear expiration warnings (sticky banner)
- One-click "Download All" for urgent galleries
- Smooth image loading with skeleton screens
- Intuitive navigation between photo categories
- Professional presentation matching photographer branding
## Key Architecture Patterns
### Authentication Flow
- JWT-based with separate tokens for admin and gallery access
- Gallery tokens include event-specific claims
- Auth middleware: `backend/src/middleware/auth.js`
- `adminAuth` - Admin panel protection
- `photoAuth` - Protected photo access
- `verifyGalleryAccess` - Gallery-specific validation
### Database Schema (Knex/SQLite)
Main tables:
- `events` - Gallery metadata with expiration, custom messages, themes
- `photos` - Photo records linked to events
- `access_logs` - IP-based usage tracking
- `email_queue` - Async email processing
- `admin_users` - Admin authentication
### Service Architecture
Background services run as separate processes:
- **emailService**: Processes email queue with retry logic
- **archiveService**: Creates ZIP archives of expired events
- **expirationChecker**: Cron job for expiration warnings
- **fileWatcher**: Monitors for new photo uploads
- **backupService**: Scheduled backups with checksum-based change detection
### API Structure
- `/api/admin/*` - Admin panel endpoints (requires adminAuth)
- `/api/gallery/*` - Public gallery endpoints
- `/api/auth/*` - Authentication endpoints
- Rate limiting: 100 req/15min (general), 5 req/15min (auth)
## Critical Implementation Notes
1. **Security**: All gallery access requires valid JWT with event-specific claims
2. **Expiration**: Events auto-expire based on `expires_at`, with 7-day email warnings
3. **Email Queue**: Async processing with retry logic, check `email_queue` table
4. **File Processing**: Sharp library for thumbnail generation (300x300)
5. **Frontend Status**: Only skeleton exists - requires full implementation based on PRD
6. **Umami Analytics**: Track password entries, downloads, views, expiration warnings
## Troubleshooting Guidelines
### Before ANY Production Troubleshooting:
1. **ALWAYS request specific details**:
- Production server URL/IP
- Current error messages/logs
- Recent changes or deployments
- Affected users/galleries
- Time of issue occurrence
2. **Thorough Analysis Required**:
- Use detailed thinking/analysis for EVERY troubleshooting task
- Review all related code before suggesting changes
- Consider all potential side effects
- Never make assumptions about production environment
3. **Safe Troubleshooting Steps**:
- First, reproduce issue in local/dev environment
- Analyze logs without modifying production
- Create detailed action plan before any changes
- Always have rollback strategy ready
- Document every step taken
### Common Issues & Safe Approaches:
- **Email not sending**: Check email_queue table, SMTP settings, service status
- **Photos not loading**: Verify file permissions, storage paths, nginx config
- **Gallery access issues**: Check JWT tokens, expiration dates, access_logs
- **Performance problems**: Analyze with monitoring tools first, never experiment
### Data Safety Rules:
- NEVER delete or modify production data without explicit backup confirmation
- ALWAYS verify backups exist before any data operations
- NO direct database modifications without transaction safety
- Log all actions for audit trail
## Environment Variables
### Backend (.env)
- `JWT_SECRET` - Token signing
- `ADMIN_URL`, `FRONTEND_URL` - CORS origins
- `SMTP_*` - Email configuration
- `DB_*` - PostgreSQL credentials (production)
- `UMAMI_URL` - Umami instance URL (for server-side tracking)
- `UMAMI_WEBSITE_ID` - Website ID from Umami
### Frontend (.env)
- `VITE_API_URL` - Backend API URL
- `VITE_UMAMI_URL` - Umami analytics URL
- `VITE_UMAMI_WEBSITE_ID` - Website ID from Umami
- `VITE_UMAMI_SHARE_URL` - (Optional) Public share URL for embedded dashboard
## Testing Approach
- Jest with Supertest for API testing
- Test files in `__tests__` directories
- Database migrations run before tests
- Mock email sending in tests
## Umami Analytics Integration
The frontend includes comprehensive Umami analytics integration for tracking user behavior and gallery performance.
### Tracked Events:
- **Gallery Events**:
- `gallery_password_entry` - Password attempts (success/failure)
- `gallery_photo_view` - Individual photo views
- `gallery_photo_download` - Single photo downloads
- `gallery_bulk_download` - Bulk/all photo downloads
- `gallery_expired` - Expired gallery access attempts
- **Admin Events**:
- `admin_login` - Admin authentication
- `admin_event_created` - New event creation
- `admin_event_archived` - Event archiving
- `admin_event_deleted` - Event deletion
- `admin_settings_updated` - Settings changes
- **User Behavior**:
- Search queries (with debouncing)
- Expiration warning views
- Page views with automatic tracking
### Setup:
1. Install Umami (self-hosted or cloud)
2. Create a website in Umami dashboard
3. Set environment variables:
```
VITE_UMAMI_URL=https://your-umami-instance.com
VITE_UMAMI_WEBSITE_ID=your-website-id
VITE_UMAMI_SHARE_URL=https://your-umami-instance.com/share/...
```
### Analytics Dashboard:
- Admin panel includes analytics page at `/admin/analytics`
- Summary view with key metrics
- Option to embed full Umami dashboard
- Real-time event tracking
## Accessibility & Performance Features
### Accessibility (WCAG 2.1 AA Compliance)
- **Error Boundaries**: Graceful error handling with recovery options
- **Skip Links**: Skip to main content for keyboard navigation
- **ARIA Labels**: Proper labeling for screen readers
- **Focus Management**: Focus trap in modals, visible focus indicators
- **Keyboard Navigation**: Full keyboard support in gallery lightbox (arrows, escape, +/-, d for download)
- **Loading States**: Skeleton screens instead of spinners for better UX
- **Offline Support**: Visual indicator when offline
- **Form Validation**: Accessible error messages with aria-describedby
### Performance Optimizations
- **Lazy Loading**: Images load on scroll with Intersection Observer
- **Skeleton Screens**: Instant visual feedback during loading
- **Error Recovery**: Component-level error boundaries prevent full page crashes
- **Optimistic Updates**: Immediate UI updates with background sync
- **Debounced Search**: Prevents excessive API calls
- **Analytics**: Non-blocking Umami integration
### Component Library Enhancements
- `<ErrorBoundary>` - Catches and displays errors gracefully
- `<PageErrorBoundary>` - Full-page error recovery
- `<Skeleton>` - Flexible skeleton loader with variants
- `<OfflineIndicator>` - Network status monitoring
- `<SkipLink>` - Accessibility navigation
- `useFocusTrap` - Modal focus management hook
- `useOnlineStatus` - Network status hook
## Theme System & Branding
### Theme Features
- **Dynamic Theming**: CSS variables for runtime theme switching
- **Preset Themes**: Default, Wedding, Birthday, Corporate, Minimal
- **Customization Options**:
- Primary/Accent/Background/Text colors
- Font family selection
- Border radius (none, sm, md, lg)
- Custom logo upload
- Custom CSS injection
- **Event-Specific Themes**: Override global theme per gallery
- **Live Preview**: Real-time theme changes in admin panel
### Theme Context API
```typescript
const { theme, setTheme, setThemeByName } = useTheme();
```
### Branding Settings
- Company name, tagline, and support email
- Custom footer text
- Optional watermarking on downloads
- Logo upload for gallery header
### CSS Variables
```css
--color-primary: #5C8762;
--color-primary-light: #7aa583;
--color-primary-dark: #4a6f4f;
--color-accent: #22c55e;
--color-background: #fafafa;
--color-text: #171717;
--font-family: 'Inter', sans-serif;
--border-radius: 0.5rem;
```
## Backup Service
### Overview
The backup service provides automated, scheduled backups of all photo data with checksum-based change detection to minimize transfer overhead.
### Features
- **Multiple Destinations**: Local directory, remote server (rsync), S3-compatible storage
- **Change Detection**: SHA256 checksums track file changes, only modified files are backed up
- **Scheduled Execution**: Configurable cron-based scheduling (default: 2 AM daily)
- **Email Notifications**: Alerts on backup failure, optional success notifications
- **Retention Management**: Automatic cleanup of old backup runs based on retention policy
- **Progress Tracking**: Database storage of backup history, file states, and statistics
### Configuration
Backup settings are stored in `app_settings` table with `backup_` prefix:
- `backup_enabled`: Enable/disable the service
- `backup_schedule`: Cron expression (e.g., '0 2 * * *')
- `backup_destination_type`: 'local', 'rsync', or 's3'
- `backup_retention_days`: How long to keep backup history
- `backup_include_archived`: Whether to backup archived events
- `backup_exclude_patterns`: File patterns to exclude
### API Endpoints
- `GET /api/admin/backup/config` - Get current configuration
- `PUT /api/admin/backup/config` - Update configuration
- `GET /api/admin/backup/status` - Get backup status and history
- `POST /api/admin/backup/run` - Trigger manual backup
- `POST /api/admin/backup/test-connection` - Test destination connectivity
### Testing
Run backup service test: `npm run test-backup`
### Database Tables
- `backup_runs`: Tracks each backup execution with statistics
- `backup_file_states`: Stores file checksums for change detection
## Thumbnail Generation
### Square Thumbnail Implementation (Issue #12 Fix)
The system now generates **square 300x300px thumbnails** to prevent blurry/stretched images in the gallery grid:
- **Problem**: Previously generated 300px width with proportional height (e.g., 300x200 for 3:2 photos), but CSS forced square display causing distortion
- **Solution**: Thumbnails now use `cover` fit mode to crop to exact 300x300px dimensions with center positioning
- **Configuration**: Settings stored in `app_settings` table with keys: `thumbnail_width`, `thumbnail_height`, `thumbnail_fit`, `thumbnail_quality`, `thumbnail_format`
- **Migration**: Run `040_add_thumbnail_settings.js` to add default square thumbnail settings
- **Regeneration Script**: Use `scripts/regenerate-square-thumbnails.js` to update existing thumbnails
### Thumbnail Settings API
- `GET /api/admin/thumbnails/settings` - Get current thumbnail configuration
- `PUT /api/admin/thumbnails/settings` - Update thumbnail settings (requires regeneration)
- `POST /api/admin/thumbnails/regenerate` - Regenerate all thumbnails with new settings
- `GET /api/admin/thumbnails/regenerate/status` - Check regeneration progress
## Success Metrics (from PRD)
- Time to generate gallery: <2 minutes
- Guest satisfaction: >90%
- System uptime: 99.9%
- Email delivery rate: >98%
- Successful archiving: 100%
## Documentation & Development Practices
### Documentation Guidelines:
- **NEVER create new documentation files for simple tasks**
- **ALWAYS update existing documentation (like this CLAUDE.md)**
- Only create new .md files when explicitly requested
- Avoid creating temporary scripts for one-off tasks
### Development Best Practices:
- Test all changes thoroughly in local environment first
- Use version control for all changes
- Keep commits atomic and well-described
- Review impact on all integrated services
- Consider backward compatibility
- Update tests when changing functionality
### Production Deployment Checklist:
- [ ] All tests passing locally
- [ ] Linting and type checks pass
- [ ] Database migrations tested with rollback plan
- [ ] Environment variables documented
- [ ] Backup strategy confirmed
- [ ] Monitoring alerts configured
- [ ] Rollback procedure documented
- [ ] Stakeholders notified of maintenance window
- always use docker deployment for testing
-372
View File
@@ -1,372 +0,0 @@
# Product Requirements Document: Event Photo Sharing Platform
## 1. Executive Summary
### 1.1 Product Overview
A secure, customizable photo sharing platform designed primarily for wedding photo booths but adaptable for any event type. The platform enables event organizers to easily share photos with guests through password-protected, time-limited links while maintaining a simple file-based backend system with automatic archiving.
### 1.2 Key Value Propositions
- **Simple Backend Management**: Drop photos in folders, generate links instantly
- **Secure Sharing**: Password-protected access with expiration dates
- **Automated Lifecycle**: Automatic archiving and storage optimization
- **Proactive Communication**: Email notifications for key events
- **Personalized Experience**: Custom branding for each event
- **Analytics Integration**: Track engagement through Umami
- **Versatile Use Cases**: Optimized for weddings but suitable for any event
## 2. Product Goals & Objectives
### 2.1 Primary Goals
- Provide a seamless, time-limited photo sharing experience for event guests
- Minimize technical complexity for administrators
- Ensure photo privacy through password protection and link expiration
- Automate storage management through intelligent archiving
- Enable detailed analytics on photo access and engagement
- Keep stakeholders informed through automated notifications
### 2.2 Success Metrics
- Time to generate new event gallery (<2 minutes)
- Guest satisfaction score (>90%)
- Photo view/download rates
- System uptime (99.9%)
- Successful automatic archiving rate (100%)
- Email delivery rate (>98%)
## 3. User Personas
### 3.1 Administrator (Event Organizer/Photographer)
- **Background**: Professional photographer or event organizer
- **Technical Skills**: Basic to intermediate
- **Needs**: Quick photo upload, easy link generation, access analytics, automated cleanup
- **Pain Points**: Complex upload processes, managing multiple events, storage management
### 3.2 End User (Event Guest)
- **Background**: Wedding guest or event attendee
- **Technical Skills**: Varies widely
- **Needs**: Easy photo viewing, downloading, sharing within timeframe
- **Pain Points**: Complicated interfaces, slow loading, expired links
### 3.3 Event Host (Bride/Groom/Celebrant)
- **Background**: Person celebrating the event
- **Technical Skills**: Basic
- **Needs**: Notification of gallery availability, awareness of expiration
- **Pain Points**: Missing the opportunity to save photos, not knowing when gallery is ready
## 4. Functional Requirements
### 4.1 Backend Administration
#### 4.1.1 File Management System
- **Photo Upload**: Direct file system access via designated folders
- **Folder Structure**:
```
/events/
├── active/
│ ├── wedding-smith-jones-2024-06-15/
│ │ ├── collages/
│ │ │ ├── collage_001.jpg
│ │ │ └── collage_002.jpg
│ │ └── individual/
│ │ ├── photo_001.jpg
│ │ └── photo_002.jpg
│ └── birthday-emma-2024-07-20/
│ └── photos/
└── archived/
└── wedding-smith-jones-2024-06-15.zip
```
- **Supported Formats**: JPEG, PNG, WebP
- **Auto-detection**: System monitors folders for new photos
- **Automatic Archiving**: Upon expiration, compress folder to ZIP and move to archive
#### 4.1.2 Link Generation
- **Unique URL Generation**: Automatic creation of shareable links
- **Password Setting**: Admin sets password during link creation
- **Expiration Date**: Mandatory expiration date selection (default: 30 days)
- **Event Metadata**:
- Event type (wedding, birthday, corporate, etc.)
- Names (couple names for weddings, celebrant for others)
- Event date
- Host email address (for notifications)
- Admin notification email
- Custom welcome message
- Color theme selection
- Link validity period
#### 4.1.3 Email Notification System
- **Trigger Events**:
- Link creation: Notify host with access details
- Link expiration warning: 7 days before expiration
- Link expiration: Notify both host and admin
- Archive completion: Confirm to admin
- **Email Templates**: Customizable, branded email templates
- **Configuration**: SMTP settings, from address, reply-to address
#### 4.1.4 Admin Dashboard
- **Event Management**: List all events, active/inactive/archived status
- **Expiration Overview**: Timeline view of upcoming expirations
- **Analytics Overview**: Quick stats per event
- **Link Management**: Copy links, reset passwords, extend expiration, deactivate events
- **Bulk Operations**: Archive old events, batch photo operations
- **Email Configuration**: Template management, SMTP settings
- **Archive Management**: View and download archived ZIPs
### 4.2 Frontend Guest Experience
#### 4.2.1 Landing Page
- **Password Entry**: Clean, intuitive password input
- **Event Preview**: Show event name, date, and expiration notice
- **Expiration Warning**: Prominent display if <7 days remaining
- **Expired State**: Clear message with contact information if expired
- **Responsive Design**: Mobile-first approach
#### 4.2.2 Gallery View
- **Expiration Banner**: Sticky banner showing days remaining
- **Grid Layout**: Responsive photo grid with lazy loading
- **View Toggle**: Switch between collages and individual photos
- **Sorting Options**: By date, name, or custom order
- **Search**: Basic filename or date search
- **Download Urgency**: Prominent "Download All" for soon-to-expire galleries
#### 4.2.3 Photo Interactions
- **Lightbox View**: Full-screen photo viewing with navigation
- **Zoom**: Pinch-to-zoom on mobile, mouse wheel on desktop
- **Download Options**:
- Single photo download
- Bulk download (selected photos)
- Download all (ZIP file)
- **Sharing**: Direct link to specific photos (respects expiration)
#### 4.2.4 Personalization
- **Dynamic Theming**: Based on event type and admin preferences
- **Custom Headers**: Event names, dates, and messages
- **Branded Elements**: Optional logo upload
- **Expiration Messaging**: Customizable expiration notices
### 4.3 Analytics Integration
#### 4.3.1 Umami Analytics
- **Page Views**: Track gallery visits
- **User Actions**: Photo views, downloads, time spent
- **Device/Browser Stats**: Understand user base
- **Geographic Data**: Guest locations
- **Custom Events**:
- Password entries (successful/failed)
- Photo downloads
- Share button clicks
- Expiration warning views
- Last-minute download spikes
### 4.4 Archiving System
#### 4.4.1 Automatic Archiving Process
- **Trigger**: Activated upon link expiration
- **Process**:
1. Create ZIP file with folder structure preserved
2. Verify ZIP integrity
3. Move ZIP to archive location
4. Delete original files
5. Update database with archive location
6. Send confirmation emails
#### 4.4.2 Archive Management
- **Storage Optimization**: Compression settings for long-term storage
- **Retrieval System**: Admin can restore archives if needed
- **Retention Policy**: Configurable long-term retention rules
## 5. Technical Requirements
### 5.1 Architecture
#### 5.1.1 Infrastructure
- **Backend Access**: Dedicated FQDN (e.g., admin.photos.domain.com)
- **Frontend Access**: Public FQDN (e.g., photos.domain.com)
- **File Storage**: Local file system or network-attached storage
- **Archive Storage**: Separate location for long-term ZIP storage
- **Database**: Lightweight database for metadata (SQLite or PostgreSQL)
- **Email Service**: SMTP integration or email service provider
#### 5.1.2 Security
- **HTTPS**: Required for both frontend and backend
- **Password Hashing**: Bcrypt or similar for stored passwords
- **Rate Limiting**: Prevent brute force attacks
- **Access Logs**: Track all access attempts
- **Expiration Enforcement**: Server-side validation of link validity
### 5.2 Performance Requirements
- **Page Load Time**: <3 seconds on 4G connection
- **Image Optimization**: Automatic thumbnail generation
- **Caching**: CDN integration for static assets
- **Concurrent Users**: Support 100+ simultaneous users per event
- **Archive Generation**: Complete within 10 minutes for 1000 photos
### 5.3 Technology Stack (Recommended)
- **Backend**: Node.js with Express or Python with FastAPI
- **Frontend**: React or Vue.js for dynamic interactions
- **Image Processing**: Sharp (Node.js) or Pillow (Python)
- **File Monitoring**: Chokidar or Watchdog
- **Analytics**: Umami self-hosted or cloud
- **Email Service**: Nodemailer or SendGrid
- **Job Queue**: Bull (Node.js) or Celery (Python) for archiving tasks
- **Scheduler**: Node-cron or APScheduler for expiration checks
## 6. User Interface Requirements
### 6.1 Design Principles
- **Modern Aesthetic**: Clean, minimalist design
- **Wedding-Optimized**: Elegant typography, romantic color options
- **Urgency Communication**: Clear expiration indicators
- **Accessibility**: WCAG 2.1 AA compliant
- **Responsive**: Mobile, tablet, and desktop optimized
### 6.2 UI Components
- **Photo Grid**: Masonry or uniform grid layout
- **Navigation**: Sticky header with view toggles
- **Expiration Timer**: Countdown display for urgent galleries
- **Loading States**: Skeleton screens for better UX
- **Error Handling**: Friendly error messages
- **Email Status**: Indicators for sent notifications
### 6.3 Branding Options
- **Color Schemes**: Pre-defined themes plus custom colors
- **Font Selection**: Google Fonts integration
- **Layout Templates**: Multiple gallery layout options
- **Email Templates**: Matching email designs
## 7. Non-Functional Requirements
### 7.1 Scalability
- Horizontal scaling capability
- Support for 10,000+ photos per event
- Efficient handling of high-resolution images
- Queue system for archiving operations
### 7.2 Reliability
- 99.9% uptime SLA
- Automated backups (including archives)
- Graceful error handling
- Failed job retry mechanisms
### 7.3 Maintainability
- Clear code documentation
- Modular architecture
- Automated testing suite
- Monitoring for failed archiving jobs
### 7.4 Compliance
- GDPR compliance for EU users
- Copyright considerations
- Privacy policy and terms of service
- Data retention policies
## 8. Email Templates
### 8.1 Link Creation Email (to Host)
- Subject: "Your [Event Name] Photos Are Ready!"
- Content: Access details, password, expiration date
- Call-to-action: View gallery button
### 8.2 Expiration Warning Email
- Subject: "Your [Event Name] Photos Expire in 7 Days"
- Content: Urgency message, download instructions
- Call-to-action: Download all photos button
### 8.3 Expiration Notification Email
- To Host: "Your [Event Name] Photo Gallery Has Expired"
- To Admin: "[Event Name] Gallery Archived Successfully"
- Content: Confirmation of archiving, contact for retrieval
## 9. Future Enhancements
### 9.1 Phase 2 Features
- **Flexible Expiration**: Extend expiration for individual users
- **Partial Downloads**: Resume interrupted downloads
- **AI-Powered Features**: Face recognition for automatic grouping
- **Social Integration**: Direct sharing to social media
- **Guest Uploads**: Allow guests to add their photos
- **Video Support**: Basic video playback
### 9.2 Phase 3 Features
- **Mobile Apps**: Native iOS/Android applications
- **Print Integration**: Direct ordering of prints
- **Event Packages**: Bundled services with photographers
- **Multi-language Support**: Internationalization
- **Cloud Archive**: Optional cloud storage for archives
## 10. Success Criteria
### 10.1 Launch Criteria
- Successfully handle 10 concurrent events
- Process 1,000 photos in <5 minutes
- 100% successful archiving rate
- Achieve 95% positive user feedback in beta
- Email delivery rate >98%
### 10.2 Post-Launch Metrics
- Monthly active events: 100+
- Average photos per event: 200+
- Guest engagement rate: 70%+
- Download rate: 50%+ of guests
- On-time archiving: 99%+
## 11. Risks & Mitigation
### 11.1 Technical Risks
- **Storage Limitations**: Implement automated archiving and cloud storage
- **Performance Issues**: Progressive loading and CDN usage
- **Security Breaches**: Regular security audits
- **Archive Failures**: Redundant archiving with verification
- **Email Delivery**: Multiple SMTP providers, delivery monitoring
### 11.2 Business Risks
- **Low Adoption**: Marketing partnerships with photographers
- **Feature Creep**: Strict MVP scope adherence
- **Support Burden**: Comprehensive documentation and FAQs
- **Expired Link Complaints**: Clear communication, grace period
## 12. Timeline & Milestones
### 12.1 Development Phases
- **Phase 1 (MVP)**: 10-12 weeks
- Core functionality
- Basic UI
- Expiration system
- Email notifications
- Archiving system
- Umami integration
- **Phase 2 (Enhancement)**: 4-6 weeks
- Advanced features
- Performance optimization
- **Phase 3 (Polish)**: 2-4 weeks
- UI refinements
- Beta testing
### 12.2 Key Milestones
- Week 2: Technical architecture finalized
- Week 4: Backend functionality complete
- Week 6: Frontend gallery functional
- Week 7: Email system integrated
- Week 8: Archiving system complete
- Week 9: Analytics integrated
- Week 12: Beta launch
## 13. Appendices
### 13.1 Technical Specifications
- Detailed API documentation
- Database schema (including expiration tracking)
- File naming conventions
- Archive format specifications
### 13.2 Design Mockups
- UI wireframes
- Email template designs
- Expiration state displays
- Style guide
- Component library
### 13.3 Testing Plan
- Unit test coverage
- Integration testing
- Archiving system testing
- Email delivery testing
- User acceptance criteria
-176
View File
@@ -1,176 +0,0 @@
#!/bin/bash
# Gitea Act Runner Installation Script
set -e
echo "==================================="
echo "Gitea Act Runner Installation"
echo "==================================="
# Configuration
GITEA_URL="https://gitea.nothaft.cloud"
RUNNER_NAME="picpeak-runner-$(hostname)"
RUNNER_VERSION="0.2.10" # Latest stable version
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${YELLOW}This script will help you install and register a Gitea Act Runner${NC}"
echo ""
# Step 1: Get registration token
echo -e "${GREEN}Step 1: Get Registration Token${NC}"
echo "1. Go to: $GITEA_URL/admin/runners"
echo "2. Click 'Create new Runner'"
echo "3. Copy the registration token"
echo ""
read -p "Enter your registration token: " REGISTRATION_TOKEN
if [ -z "$REGISTRATION_TOKEN" ]; then
echo -e "${RED}Error: Registration token is required${NC}"
exit 1
fi
# Step 2: Choose installation method
echo ""
echo -e "${GREEN}Step 2: Choose Installation Method${NC}"
echo "1. Docker (Recommended)"
echo "2. Binary installation"
read -p "Choose method (1 or 2): " METHOD
if [ "$METHOD" == "1" ]; then
# Docker installation
echo ""
echo -e "${GREEN}Installing with Docker...${NC}"
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
echo -e "${RED}Error: Docker is not installed${NC}"
echo "Please install Docker first: https://docs.docker.com/get-docker/"
exit 1
fi
# Create docker-compose file for runner
cat > docker-compose.runner.yml << EOF
version: '3.8'
services:
gitea-runner:
image: gitea/act_runner:latest
container_name: gitea-runner
restart: unless-stopped
environment:
- GITEA_INSTANCE_URL=$GITEA_URL
- GITEA_RUNNER_REGISTRATION_TOKEN=$REGISTRATION_TOKEN
- GITEA_RUNNER_NAME=$RUNNER_NAME
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./runner-data:/data
networks:
- picpeak
networks:
picpeak:
external: true
EOF
echo "Starting Gitea Runner with Docker..."
docker-compose -f docker-compose.runner.yml up -d
echo ""
echo -e "${GREEN}✓ Runner installed and started with Docker${NC}"
echo "Check logs with: docker logs gitea-runner"
elif [ "$METHOD" == "2" ]; then
# Binary installation
echo ""
echo -e "${GREEN}Installing binary...${NC}"
# Detect OS and architecture
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "$ARCH" in
x86_64)
ARCH="amd64"
;;
aarch64|arm64)
ARCH="arm64"
;;
*)
echo -e "${RED}Unsupported architecture: $ARCH${NC}"
exit 1
;;
esac
# Download act_runner
DOWNLOAD_URL="https://gitea.com/gitea/act_runner/releases/download/v${RUNNER_VERSION}/act_runner-${RUNNER_VERSION}-${OS}-${ARCH}"
echo "Downloading from: $DOWNLOAD_URL"
curl -L -o act_runner "$DOWNLOAD_URL"
chmod +x act_runner
# Create config directory
mkdir -p ~/.config/act_runner
# Register the runner
echo ""
echo -e "${GREEN}Registering runner...${NC}"
./act_runner register \
--no-interactive \
--instance "$GITEA_URL" \
--token "$REGISTRATION_TOKEN" \
--name "$RUNNER_NAME" \
--labels "ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,ubuntu-20.04:docker://node:16-bullseye"
# Create systemd service
if [ "$OS" == "linux" ]; then
echo ""
echo -e "${GREEN}Creating systemd service...${NC}"
sudo tee /etc/systemd/system/gitea-runner.service > /dev/null << EOF
[Unit]
Description=Gitea Act Runner
After=network.target
[Service]
Type=simple
User=$USER
WorkingDirectory=$PWD
ExecStart=$PWD/act_runner daemon
Restart=always
RestartSec=5
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable gitea-runner
sudo systemctl start gitea-runner
echo -e "${GREEN}✓ Runner installed as systemd service${NC}"
echo "Check status with: sudo systemctl status gitea-runner"
echo "Check logs with: sudo journalctl -u gitea-runner -f"
else
echo ""
echo -e "${GREEN}✓ Runner installed${NC}"
echo "Start runner with: ./act_runner daemon"
fi
fi
echo ""
echo -e "${GREEN}==================================="
echo "Installation Complete!"
echo "===================================${NC}"
echo ""
echo "Next steps:"
echo "1. Go to: $GITEA_URL/paul/picpeak/settings/actions/runners"
echo "2. Verify your runner appears in the list"
echo "3. Push a commit to trigger the test workflow"
echo ""
echo "If the runner doesn't appear, check the logs for errors."
View File
View File
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 853 KiB