diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 97a8bd46..00000000 --- a/.codecov.yml +++ /dev/null @@ -1,36 +0,0 @@ -# Codecov configuration - require 75% overall coverage by default -# Adjust target as needed - -coverage: - status: - project: - default: - target: 75% - threshold: 0% - -# Fail CI if Codecov upload/report indicates a problem -require_ci_to_pass: yes - -# Exclude folders from Codecov -ignore: - - "**/tests/*" - - "**/test/*" - - "**/__tests__/*" - - "**/test_*.go" - - "**/*_test.go" - - "**/*.test.ts" - - "**/*.test.tsx" - - "docs/*" - - ".github/*" - - "scripts/*" - - "tools/*" - - "frontend/node_modules/*" - - "frontend/dist/*" - - "frontend/coverage/*" - - "backend/cmd/seed/*" - - "backend/cmd/api/*" - - "backend/data/*" - - "backend/coverage/*" - - "backend/internal/services/docker_service.go" - - "backend/internal/api/handlers/docker_handler.go" - - "*.md" diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 83d95583..00000000 --- a/.dockerignore +++ /dev/null @@ -1,82 +0,0 @@ -# Version control -.git -.gitignore -.github/ - -# Python -__pycache__/ -*.py[cod] -*$py.class -*.so -.Python -.venv/ -venv/ -env/ -ENV/ -.pytest_cache/ -.coverage -*.cover -.hypothesis/ -htmlcov/ -*.egg-info/ - -# Node/Frontend build artifacts -frontend/node_modules/ -frontend/coverage/ -frontend/coverage.out -frontend/dist/ -frontend/.vite/ -frontend/*.tsbuildinfo -frontend/frontend/ - -# Go/Backend -backend/coverage.txt -backend/*.out -backend/coverage/ -backend/coverage.*.out -backend/package.json -backend/package-lock.json - -# Databases (runtime) -backend/data/*.db -backend/cmd/api/data/*.db -*.sqlite -*.sqlite3 - -# IDE -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# Logs -.trivy_logs -*.log -logs/ - -# Environment -.env -.env.local -.env.*.local - -# OS -.DS_Store -Thumbs.db - -# Documentation -docs/ -*.md -!README.md - -# Docker -docker-compose*.yml -**/Dockerfile.* - -# CI/CD -.github/ -.pre-commit-config.yaml - -# Scripts -scripts/ -tools/ diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 706def22..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,14 +0,0 @@ -# These are supported funding model platforms -github: Wikid82 -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -polar: # Replace with a single Polar username -buy_me_a_coffee: Wikid82 -thanks_dev: # Replace with a single thanks.dev username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE/alpha-feature.yml b/.github/ISSUE_TEMPLATE/alpha-feature.yml deleted file mode 100644 index 51d0cc0d..00000000 --- a/.github/ISSUE_TEMPLATE/alpha-feature.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: 🏗️ Alpha Feature -description: Create an issue for an Alpha milestone feature -title: "[ALPHA] " -labels: ["alpha", "feature"] -body: - - type: markdown - attributes: - value: | - ## Alpha Milestone Feature - Features that are part of the core foundation and initial release. - - - type: dropdown - id: priority - attributes: - label: Priority - description: How critical is this feature? - options: - - Critical (Blocking, must-have) - - High (Important, should have) - - Medium (Nice to have) - - Low (Future enhancement) - validations: - required: true - - - type: input - id: issue_number - attributes: - label: Planning Issue Number - description: Reference number from PROJECT_PLANNING.md (e.g., Issue #5) - placeholder: "Issue #" - validations: - required: false - - - type: textarea - id: description - attributes: - label: Feature Description - description: What should this feature do? - placeholder: Describe the feature in detail - validations: - required: true - - - type: textarea - id: tasks - attributes: - label: Implementation Tasks - description: List of tasks to complete this feature - placeholder: | - - [ ] Task 1 - - [ ] Task 2 - - [ ] Task 3 - value: | - - [ ] - validations: - required: true - - - type: textarea - id: acceptance - attributes: - label: Acceptance Criteria - description: How do we know this feature is complete? - placeholder: | - - [ ] Criteria 1 - - [ ] Criteria 2 - value: | - - [ ] - validations: - required: true - - - type: checkboxes - id: categories - attributes: - label: Categories - description: Select all that apply - options: - - label: Backend - - label: Frontend - - label: Database - - label: Caddy Integration - - label: Security - - label: SSL/TLS - - label: UI/UX - - label: Deployment - - label: Documentation - - - type: textarea - id: technical_notes - attributes: - label: Technical Notes - description: Any technical considerations or dependencies? - placeholder: Libraries, APIs, or other issues that need to be completed first - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/beta-monitoring-feature.yml b/.github/ISSUE_TEMPLATE/beta-monitoring-feature.yml deleted file mode 100644 index b1965956..00000000 --- a/.github/ISSUE_TEMPLATE/beta-monitoring-feature.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: 📊 Beta Monitoring Feature -description: Create an issue for a Beta milestone monitoring/logging feature -title: "[BETA] [MONITORING] " -labels: ["beta", "feature", "monitoring"] -body: - - type: markdown - attributes: - value: | - ## Beta Monitoring & Logging Feature - Features related to observability, logging, and system monitoring. - - - type: dropdown - id: priority - attributes: - label: Priority - description: How critical is this monitoring feature? - options: - - Critical (Essential for operations) - - High (Important visibility) - - Medium (Enhanced monitoring) - - Low (Nice-to-have metrics) - validations: - required: true - - - type: dropdown - id: monitoring_type - attributes: - label: Monitoring Type - description: What aspect of monitoring? - options: - - Dashboards & Statistics - - Log Viewing & Search - - Alerting & Notifications - - CrowdSec Dashboard - - Analytics Integration - - Health Checks - - Performance Metrics - validations: - required: true - - - type: input - id: issue_number - attributes: - label: Planning Issue Number - description: Reference number from PROJECT_PLANNING.md (e.g., Issue #23) - placeholder: "Issue #" - validations: - required: false - - - type: textarea - id: description - attributes: - label: Feature Description - description: What monitoring/logging capability should this provide? - placeholder: Describe what users will be able to see or do - validations: - required: true - - - type: textarea - id: metrics - attributes: - label: Metrics & Data Points - description: What data will be collected and displayed? - placeholder: | - - Metric 1: Description - - Metric 2: Description - validations: - required: false - - - type: textarea - id: tasks - attributes: - label: Implementation Tasks - description: List of tasks to complete this feature - placeholder: | - - [ ] Task 1 - - [ ] Task 2 - - [ ] Task 3 - value: | - - [ ] - validations: - required: true - - - type: textarea - id: acceptance - attributes: - label: Acceptance Criteria - description: How do we verify this monitoring feature works? - placeholder: | - - [ ] Data displays correctly - - [ ] Updates in real-time - - [ ] Performance is acceptable - value: | - - [ ] - validations: - required: true - - - type: checkboxes - id: categories - attributes: - label: Implementation Areas - description: Select all that apply - options: - - label: Backend (Data collection) - - label: Frontend (UI/Charts) - - label: Database (Storage) - - label: Real-time Updates (WebSocket) - - label: External Integration (GoAccess, CrowdSec) - - label: Documentation Required - - - type: textarea - id: ui_design - attributes: - label: UI/UX Considerations - description: Describe the user interface requirements - placeholder: Layout, charts, filters, export options, etc. - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/beta-security-feature.yml b/.github/ISSUE_TEMPLATE/beta-security-feature.yml deleted file mode 100644 index d28c9d0d..00000000 --- a/.github/ISSUE_TEMPLATE/beta-security-feature.yml +++ /dev/null @@ -1,116 +0,0 @@ -name: 🔐 Beta Security Feature -description: Create an issue for a Beta milestone security feature -title: "[BETA] [SECURITY] " -labels: ["beta", "feature", "security"] -body: - - type: markdown - attributes: - value: | - ## Beta Security Feature - Advanced security features for the beta release. - - - type: dropdown - id: priority - attributes: - label: Priority - description: How critical is this security feature? - options: - - Critical (Essential security control) - - High (Important protection) - - Medium (Additional hardening) - - Low (Nice-to-have security enhancement) - validations: - required: true - - - type: dropdown - id: security_category - attributes: - label: Security Category - description: What type of security feature is this? - options: - - Authentication & Access Control - - Threat Protection - - SSL/TLS Management - - Monitoring & Logging - - Web Application Firewall - - Rate Limiting - - IP Access Control - validations: - required: true - - - type: input - id: issue_number - attributes: - label: Planning Issue Number - description: Reference number from PROJECT_PLANNING.md (e.g., Issue #15) - placeholder: "Issue #" - validations: - required: false - - - type: textarea - id: description - attributes: - label: Feature Description - description: What security capability should this provide? - placeholder: Describe the security feature and its purpose - validations: - required: true - - - type: textarea - id: threat_model - attributes: - label: Threat Model - description: What threats does this feature mitigate? - placeholder: | - - Threat 1: Description and severity - - Threat 2: Description and severity - validations: - required: false - - - type: textarea - id: tasks - attributes: - label: Implementation Tasks - description: List of tasks to complete this feature - placeholder: | - - [ ] Task 1 - - [ ] Task 2 - - [ ] Task 3 - value: | - - [ ] - validations: - required: true - - - type: textarea - id: acceptance - attributes: - label: Acceptance Criteria - description: How do we verify this security control works? - placeholder: | - - [ ] Security test 1 - - [ ] Security test 2 - value: | - - [ ] - validations: - required: true - - - type: checkboxes - id: special_labels - attributes: - label: Special Categories - description: Select all that apply - options: - - label: SSO (Single Sign-On) - - label: WAF (Web Application Firewall) - - label: CrowdSec Integration - - label: Plus Feature (Premium) - - label: Requires Documentation - - - type: textarea - id: security_testing - attributes: - label: Security Testing Plan - description: How will you test this security feature? - placeholder: Describe testing approach, tools, and scenarios - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index dd84ea78..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/general-feature.yml b/.github/ISSUE_TEMPLATE/general-feature.yml deleted file mode 100644 index 497d7735..00000000 --- a/.github/ISSUE_TEMPLATE/general-feature.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: ⚙️ General Feature -description: Create a feature request for any milestone -title: "[FEATURE] " -labels: ["feature"] -body: - - type: markdown - attributes: - value: | - ## Feature Request - Request a new feature or enhancement for CaddyProxyManager+ - - - type: dropdown - id: milestone - attributes: - label: Target Milestone - description: Which release should this be part of? - options: - - Alpha (Core foundation) - - Beta (Advanced features) - - Post-Beta (Future enhancements) - - Unsure (Help me decide) - validations: - required: true - - - type: dropdown - id: priority - attributes: - label: Priority - description: How important is this feature? - options: - - Critical - - High - - Medium - - Low - validations: - required: true - - - type: textarea - id: problem - attributes: - label: Problem Statement - description: What problem does this feature solve? - placeholder: Describe the use case or pain point - validations: - required: true - - - type: textarea - id: solution - attributes: - label: Proposed Solution - description: How should this feature work? - placeholder: Describe your ideal implementation - validations: - required: true - - - type: textarea - id: alternatives - attributes: - label: Alternatives Considered - description: What other approaches could solve this? - placeholder: List alternative solutions you've thought about - validations: - required: false - - - type: textarea - id: user_story - attributes: - label: User Story - description: Describe this from a user's perspective - placeholder: "As a [user type], I want to [action] so that [benefit]" - validations: - required: false - - - type: checkboxes - id: categories - attributes: - label: Feature Categories - description: Select all that apply - options: - - label: Authentication/Authorization - - label: Security - - label: SSL/TLS - - label: Monitoring/Logging - - label: UI/UX - - label: Performance - - label: Documentation - - label: API - - label: Plus Feature (Premium) - - - type: textarea - id: additional - attributes: - label: Additional Context - description: Any other information, screenshots, or examples? - placeholder: Add links, mockups, or references - validations: - required: false diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 9a11e9ff..00000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,43 +0,0 @@ -# CaddyProxyManager+ Copilot Instructions - -## 🚨 CRITICAL ARCHITECTURE RULES 🚨 -- **Single Frontend Source**: All frontend code MUST reside in `frontend/`. NEVER create `backend/frontend/` or any other nested frontend directory. -- **Single Backend Source**: All backend code MUST reside in `backend/`. -- **No Python**: This is a Go (Backend) + React/TypeScript (Frontend) project. Do not introduce Python scripts or requirements. - -## Big Picture -- `backend/cmd/api` loads config, opens SQLite, then hands off to `internal/server` where routes from `internal/api/routes` are registered. -- `internal/config` respects `CPM_ENV`, `CPM_HTTP_PORT`, `CPM_DB_PATH`, `CPM_FRONTEND_DIR` and creates the `data/` directory; lean on these instead of hard-coded paths. -- All HTTP endpoints live under `/api/v1/*`; keep new handlers inside `internal/api/handlers` and register them via `routes.Register` so `db.AutoMigrate` runs for their models. -- `internal/server` also mounts the built React app (via `attachFrontend`) whenever `frontend/dist` exists, falling back to JSON `{"error": ...}` for any `/api/*` misses. -- Persistent types live in `internal/models`; GORM auto-migrates them each boot, so evolve schemas there before touching handlers or the frontend. - -## Backend Workflow -- Run locally with `cd backend && go run ./cmd/api`; run tests with `go test ./...` (see `proxy_host_handler_test.go` for the in-memory SQLite/Gin harness pattern). -- Handlers return structured errors using `gin.H{"error": "message"}` and standard HTTP codes—mirror the `ProxyHostHandler` lifecycle for new CRUD endpoints. -- UUIDs (`github.com/google/uuid`) are generated server-side and exposed as `uuid` fields; clients never send numeric IDs. -- Query lists sorted by `updated_at desc` (see `.Order("updated_at desc")` in `List`); match that ordering for user-visible collections. -- Long-running work must respect the graceful shutdown flow in `server.Run(ctx)`—avoid background goroutines that ignore the context. - -## Frontend Workflow -- **Location**: Always work within `frontend/`. -- **Stack**: React 18 + Vite + TypeScript + TanStack Query (React Query). -- **State Management**: Use `src/hooks/use*.ts` wrapping React Query. Do not use raw `useEffect` for data fetching. -- **API Layer**: Create typed API clients in `src/api/*.ts` that wrap `client.ts`. -- **Development**: Run `cd frontend && npm run dev`. Vite proxies `/api` to `http://localhost:8080`. -- **Components**: Screens live in `src/pages`. Reusable UI in `src/components`. -- **Forms**: Use local `useState` for form fields, submit via `useMutation` from custom hooks, then `invalidateQueries` on success. - -## Cross-Cutting Notes -- Run the backend before the frontend; React Query expects the exact JSON produced by GORM tags (snake_case), so keep API and UI field names aligned. -- When adding models, update both `internal/models` and the `AutoMigrate` call inside `internal/api/routes/routes.go`; register new Gin routes right after migrations for clarity. -- Tests belong beside handlers (`*_test.go`); reuse the `setupTestRouter` helper structure (in-memory SQLite, Gin router, httptest requests) for fast feedback. -- **Testing Requirement**: All new code (features, bug fixes, refactors) MUST include accompanying unit tests. Ensure tests cover happy paths and error conditions. -- **Ignore Files**: When creating new file types, directories, or build artifacts, ALWAYS check and update `.gitignore`, `.dockerignore`, and `.codecov.yml` to ensure they are properly excluded or included as required. -- The root `Dockerfile` builds the Go binary and the React static assets (multi-stage build). -- Branch from `feature/**` and target `development`. - -## CI/CD & Commit Conventions -- **Docker Builds**: The `docker-publish` workflow skips builds for commits starting with `chore:`. -- **Triggering Builds**: To ensure a new Docker image is built (e.g., for testing on VPS), use `feat:`, `fix:`, or `perf:` prefixes. -- **Beta Branch**: The `feature/beta-release` branch is configured to ALWAYS build, overriding the skip logic. diff --git a/.github/renovate.json b/.github/renovate.json deleted file mode 100644 index 8302d397..00000000 --- a/.github/renovate.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended", - ":semanticCommits", - ":separateMultipleMajorReleases", - "helpers:pinGitHubActionDigests" - ], - "baseBranches": ["development"], - "timezone": "UTC", - "dependencyDashboard": true, - "prConcurrentLimit": 10, - "prHourlyLimit": 5, - "labels": ["dependencies"], - "rebaseWhen": "conflicted", - "vulnerabilityAlerts": { "enabled": true }, - "schedule": ["every weekday"], - "rangeStrategy": "bump", - "packageRules": [ - { - "description": "Automerge safe patch updates", - "matchUpdateTypes": ["patch"], - "automerge": true - }, - { - "description": "Frontend npm: automerge minor for devDependencies", - "matchManagers": ["npm"], - "matchDepTypes": ["devDependencies"], - "matchUpdateTypes": ["minor", "patch"], - "automerge": true, - "labels": ["dependencies", "npm"] - }, - { - "description": "Backend Go modules", - "matchManagers": ["gomod"], - "labels": ["dependencies", "go"], - "matchUpdateTypes": ["minor", "patch"], - "automerge": false - }, - { - "description": "GitHub Actions updates", - "matchManagers": ["github-actions"], - "labels": ["dependencies", "github-actions"], - "matchUpdateTypes": ["minor", "patch"], - "automerge": true - }, - { - "description": "Docker: keep Caddy within v2 (no automatic jump to v3)", - "matchManagers": ["dockerfile"], - "matchPackageNames": ["caddy"], - "allowedVersions": "<3.0.0", - "labels": ["dependencies", "docker"], - "automerge": true - }, - { - "description": "Group non-breaking npm minor/patch", - "matchManagers": ["npm"], - "matchUpdateTypes": ["minor", "patch"], - "groupName": "npm minor/patch", - "prPriority": -1 - }, - { - "description": "Group docker base minor/patch", - "matchManagers": ["dockerfile"], - "matchUpdateTypes": ["minor", "patch"], - "groupName": "docker base updates", - "prPriority": -1 - } - ] -} diff --git a/.github/workflows/auto-add-to-project.yml b/.github/workflows/auto-add-to-project.yml deleted file mode 100644 index 78804bb8..00000000 --- a/.github/workflows/auto-add-to-project.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Auto-add issues and PRs to Project - -on: - issues: - types: [opened, reopened] - pull_request: - types: [opened, reopened] - -jobs: - add-to-project: - runs-on: ubuntu-latest - steps: - - name: Determine project URL presence - id: project_check - run: | - if [ -n "${{ secrets.PROJECT_URL }}" ]; then - echo "has_project=true" >> $GITHUB_OUTPUT - else - echo "has_project=false" >> $GITHUB_OUTPUT - fi - - - name: Add issue or PR to project - if: steps.project_check.outputs.has_project == 'true' - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 - continue-on-error: true - with: - project-url: ${{ secrets.PROJECT_URL }} - github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} - - - name: Skip summary - if: steps.project_check.outputs.has_project == 'false' - run: echo "PROJECT_URL secret missing; skipping project assignment." >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/auto-label-issues.yml b/.github/workflows/auto-label-issues.yml deleted file mode 100644 index cdbafdbd..00000000 --- a/.github/workflows/auto-label-issues.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: Auto-label Issues - -on: - issues: - types: [opened, edited] - -jobs: - auto-label: - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: Auto-label based on title and body - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const issue = context.payload.issue; - const title = issue.title.toLowerCase(); - const body = issue.body ? issue.body.toLowerCase() : ''; - const labels = []; - - // Priority detection - if (title.includes('[critical]') || body.includes('priority: critical')) { - labels.push('critical'); - } else if (title.includes('[high]') || body.includes('priority: high')) { - labels.push('high'); - } else if (title.includes('[medium]') || body.includes('priority: medium')) { - labels.push('medium'); - } else if (title.includes('[low]') || body.includes('priority: low')) { - labels.push('low'); - } - - // Milestone detection - if (title.includes('[alpha]') || body.includes('milestone: alpha')) { - labels.push('alpha'); - } else if (title.includes('[beta]') || body.includes('milestone: beta')) { - labels.push('beta'); - } else if (title.includes('[post-beta]') || body.includes('milestone: post-beta')) { - labels.push('post-beta'); - } - - // Category detection - if (title.includes('architecture') || body.includes('architecture')) labels.push('architecture'); - if (title.includes('backend') || body.includes('backend')) labels.push('backend'); - if (title.includes('frontend') || body.includes('frontend')) labels.push('frontend'); - if (title.includes('security') || body.includes('security')) labels.push('security'); - if (title.includes('ssl') || title.includes('tls') || body.includes('certificate')) labels.push('ssl'); - if (title.includes('sso') || body.includes('single sign-on')) labels.push('sso'); - if (title.includes('waf') || body.includes('web application firewall')) labels.push('waf'); - if (title.includes('crowdsec') || body.includes('crowdsec')) labels.push('crowdsec'); - if (title.includes('caddy') || body.includes('caddy')) labels.push('caddy'); - if (title.includes('database') || body.includes('database')) labels.push('database'); - if (title.includes('ui') || title.includes('interface')) labels.push('ui'); - if (title.includes('docker') || title.includes('deployment')) labels.push('deployment'); - if (title.includes('monitoring') || title.includes('logging')) labels.push('monitoring'); - if (title.includes('documentation') || title.includes('docs')) labels.push('documentation'); - if (title.includes('test') || body.includes('testing')) labels.push('testing'); - if (title.includes('performance') || body.includes('optimization')) labels.push('performance'); - if (title.includes('plus') || body.includes('premium feature')) labels.push('plus'); - - // Feature detection - if (title.includes('feature') || body.includes('feature request')) labels.push('feature'); - - // Only add labels if we detected any - if (labels.length > 0) { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - labels: labels - }); - - console.log(`Added labels: ${labels.join(', ')}`); - } diff --git a/.github/workflows/caddy-major-monitor.yml b/.github/workflows/caddy-major-monitor.yml deleted file mode 100644 index 74a1921b..00000000 --- a/.github/workflows/caddy-major-monitor.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Monitor Caddy Major Release - -on: - schedule: - - cron: '17 7 * * 1' # Mondays at 07:17 UTC - workflow_dispatch: {} - -permissions: - contents: read - issues: write - -jobs: - check-caddy-major: - runs-on: ubuntu-latest - steps: - - name: Check for Caddy v3 and open issue - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const upstream = { owner: 'caddyserver', repo: 'caddy' }; - const { data: releases } = await github.rest.repos.listReleases({ - ...upstream, - per_page: 50, - }); - const latestV3 = releases.find(r => /^v3\./.test(r.tag_name)); - if (!latestV3) { - core.info('No Caddy v3 release detected.'); - return; - } - - const issueTitle = `Track upgrade to Caddy v3 (${latestV3.tag_name})`; - - const { data: existing } = await github.rest.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - per_page: 100, - }); - - if (existing.some(i => i.title === issueTitle)) { - core.info('Issue already exists — nothing to do.'); - return; - } - - const body = [ - 'Caddy v3 has been released upstream and detected by the scheduled monitor.', - '', - `Detected release: ${latestV3.tag_name} (${latestV3.html_url})`, - '', - '- Create a feature branch to evaluate the v3 migration.', - '- Review breaking changes and update Docker base images/workflows.', - '- Validate Trivy scans and update any policies as needed.', - '', - 'Current policy: remain on latest 2.x until v3 is validated.' - ].join('\n'); - - await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: issueTitle, - body, - }); diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index d17a521a..00000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: CodeQL - Analyze - -on: - push: - branches: [ main, development, 'feature/**' ] - pull_request: - branches: [ main, development ] - schedule: - - cron: '0 3 * * 1' - -permissions: - contents: read - security-events: write - actions: read - pull-requests: read - -jobs: - analyze: - name: CodeQL analysis (${{ matrix.language }}) - runs-on: ubuntu-latest - # Skip forked PRs where CPMP_TOKEN lacks security-events permissions - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false - permissions: - contents: read - security-events: write - actions: read - pull-requests: read - strategy: - fail-fast: false - matrix: - language: [ 'go', 'javascript-typescript' ] - steps: - - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6 - - - name: Initialize CodeQL - uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4 - with: - languages: ${{ matrix.language }} - - - name: Autobuild - uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4 - with: - category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/create-labels.yml b/.github/workflows/create-labels.yml deleted file mode 100644 index 21670aac..00000000 --- a/.github/workflows/create-labels.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: Create Project Labels - -# This workflow only runs manually to set up labels -on: - workflow_dispatch: - -jobs: - create-labels: - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: Create all project labels - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - with: - script: | - const labels = [ - // Priority labels - { name: 'critical', color: 'B60205', description: 'Must have for the release, blocks other work' }, - { name: 'high', color: 'D93F0B', description: 'Important feature, should be included' }, - { name: 'medium', color: 'FBCA04', description: 'Nice to have, can be deferred' }, - { name: 'low', color: '0E8A16', description: 'Future enhancement, not urgent' }, - - // Milestone labels - { name: 'alpha', color: '5319E7', description: 'Part of initial alpha release' }, - { name: 'beta', color: '0052CC', description: 'Part of beta release' }, - { name: 'post-beta', color: '006B75', description: 'Post-beta enhancement' }, - - // Category labels - { name: 'architecture', color: 'C5DEF5', description: 'System design and structure' }, - { name: 'backend', color: '1D76DB', description: 'Server-side code' }, - { name: 'frontend', color: '5EBEFF', description: 'UI/UX code' }, - { name: 'feature', color: 'A2EEEF', description: 'New functionality' }, - { name: 'security', color: 'EE0701', description: 'Security-related' }, - { name: 'ssl', color: 'F9D0C4', description: 'SSL/TLS certificates' }, - { name: 'sso', color: 'D4C5F9', description: 'Single Sign-On' }, - { name: 'waf', color: 'B60205', description: 'Web Application Firewall' }, - { name: 'crowdsec', color: 'FF6B6B', description: 'CrowdSec integration' }, - { name: 'caddy', color: '1F6FEB', description: 'Caddy-specific' }, - { name: 'database', color: '006B75', description: 'Database-related' }, - { name: 'ui', color: '7057FF', description: 'User interface' }, - { name: 'deployment', color: '0E8A16', description: 'Docker, installation' }, - { name: 'monitoring', color: 'FEF2C0', description: 'Logging and statistics' }, - { name: 'documentation', color: '0075CA', description: 'Docs and guides' }, - { name: 'testing', color: 'BFD4F2', description: 'Test suite' }, - { name: 'performance', color: 'EDEDED', description: 'Optimization' }, - { name: 'community', color: 'D876E3', description: 'Community building' }, - { name: 'plus', color: 'FFD700', description: 'Premium/"Plus" feature' }, - { name: 'enterprise', color: '8B4513', description: 'Enterprise-grade feature' } - ]; - - for (const label of labels) { - try { - await github.rest.issues.createLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - name: label.name, - color: label.color, - description: label.description - }); - console.log(`✓ Created label: ${label.name}`); - } catch (error) { - if (error.status === 422) { - console.log(`⚠ Label already exists: ${label.name}`); - // Update the label if it exists - await github.rest.issues.updateLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - name: label.name, - color: label.color, - description: label.description - }); - console.log(`✓ Updated label: ${label.name}`); - } else { - console.error(`✗ Error creating label ${label.name}:`, error.message); - } - } - } diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml deleted file mode 100644 index a10b7079..00000000 --- a/.github/workflows/docker-publish.yml +++ /dev/null @@ -1,252 +0,0 @@ -name: Docker Build, Publish & Test - -on: - push: - branches: - - main - - development - - feature/beta-release - tags: - - 'v*.*.*' - pull_request: - branches: - - main - - development - - feature/beta-release - workflow_dispatch: - workflow_call: - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository_owner }}/cpmp - -jobs: - build-and-push: - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - packages: write - security-events: write - - outputs: - skip_build: ${{ steps.skip.outputs.skip_build }} - digest: ${{ steps.build-and-push.outputs.digest }} - - steps: - - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - - - name: Normalize image name - run: | - echo "IMAGE_NAME=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - - - name: Determine skip condition - id: skip - env: - ACTOR: ${{ github.actor }} - EVENT: ${{ github.event_name }} - HEAD_MSG: ${{ github.event.head_commit.message }} - REF: ${{ github.ref }} - run: | - should_skip=false - pr_title="" - if [ "$EVENT" = "pull_request" ]; then - pr_title=$(jq -r '.pull_request.title' "$GITHUB_EVENT_PATH" 2>/dev/null || echo '') - fi - if [ "$ACTOR" = "renovate[bot]" ]; then should_skip=true; fi - if echo "$HEAD_MSG" | grep -Ei '^chore\(deps' >/dev/null 2>&1; then should_skip=true; fi - if echo "$HEAD_MSG" | grep -Ei '^chore:' >/dev/null 2>&1; then should_skip=true; fi - if echo "$pr_title" | grep -Ei '^chore\(deps' >/dev/null 2>&1; then should_skip=true; fi - if echo "$pr_title" | grep -Ei '^chore:' >/dev/null 2>&1; then should_skip=true; fi - - # Always build on beta-release branch to ensure artifacts for testing - if [[ "$REF" == "refs/heads/feature/beta-release" ]]; then - should_skip=false - echo "Force building on beta-release branch" - fi - - echo "skip_build=$should_skip" >> $GITHUB_OUTPUT - - - name: Set up QEMU - if: steps.skip.outputs.skip_build != 'true' - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - - name: Set up Docker Buildx - if: steps.skip.outputs.skip_build != 'true' - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - - name: Resolve Caddy base digest - if: steps.skip.outputs.skip_build != 'true' - id: caddy - run: | - docker pull caddy:2-alpine - DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' caddy:2-alpine) - echo "image=$DIGEST" >> $GITHUB_OUTPUT - - - name: Log in to Container Registry - if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true' - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.CPMP_TOKEN }} - - - name: Extract metadata (tags, labels) - if: steps.skip.outputs.skip_build != 'true' - id: meta - uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=raw,value=dev,enable=${{ github.ref == 'refs/heads/development' }} - type=raw,value=beta,enable=${{ github.ref == 'refs/heads/feature/beta-release' }} - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value=pr-${{ github.ref_name }},enable=${{ github.event_name == 'pull_request' }} - type=sha,format=short,enable=${{ github.event_name != 'pull_request' }} - - - name: Build and push Docker image - if: steps.skip.outputs.skip_build != 'true' - id: build-and-push - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6 - with: - context: . - platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || 'linux/amd64,linux/arm64' }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - build-args: | - VERSION=${{ steps.meta.outputs.version }} - BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} - VCS_REF=${{ github.sha }} - CADDY_IMAGE=${{ steps.caddy.outputs.image }} - - - name: Run Trivy scan (table output) - if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true' - uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 - with: - image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }} - format: 'table' - severity: 'CRITICAL,HIGH' - exit-code: '0' - continue-on-error: true - - - name: Run Trivy vulnerability scanner (SARIF) - if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true' - id: trivy - uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 - with: - image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }} - format: 'sarif' - output: 'trivy-results.sarif' - severity: 'CRITICAL,HIGH' - continue-on-error: true - - - name: Check Trivy SARIF exists - if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true' - id: trivy-check - run: | - if [ -f trivy-results.sarif ]; then - echo "exists=true" >> $GITHUB_OUTPUT - else - echo "exists=false" >> $GITHUB_OUTPUT - fi - - - name: Upload Trivy results - if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true' && steps.trivy-check.outputs.exists == 'true' - uses: github/codeql-action/upload-sarif@d3ced5c96c16c4332e2a61eb6f3649d6f1b20bb8 # v3.31.5 - with: - sarif_file: 'trivy-results.sarif' - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Create summary - if: steps.skip.outputs.skip_build != 'true' - run: | - echo "## 🎉 Docker Image Built Successfully!" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### 📦 Image Details" >> $GITHUB_STEP_SUMMARY - echo "- **Registry**: GitHub Container Registry (ghcr.io)" >> $GITHUB_STEP_SUMMARY - echo "- **Repository**: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" >> $GITHUB_STEP_SUMMARY - echo "- **Tags**: " >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - - test-image: - name: Test Docker Image - needs: build-and-push - runs-on: ubuntu-latest - if: needs.build-and-push.outputs.skip_build != 'true' && github.event_name != 'pull_request' - - steps: - - name: Normalize image name - run: | - raw="${{ github.repository_owner }}/${{ github.event.repository.name }}" - echo "IMAGE_NAME=$(echo "$raw" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - - - name: Determine image tag - id: tag - run: | - if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then - echo "tag=latest" >> $GITHUB_OUTPUT - elif [[ "${{ github.ref }}" == "refs/heads/development" ]]; then - echo "tag=dev" >> $GITHUB_OUTPUT - elif [[ "${{ github.ref }}" == refs/tags/v* ]]; then - echo "tag=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT - else - echo "tag=sha-$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT - fi - - - name: Log in to GitHub Container Registry - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.CPMP_TOKEN }} - - - name: Pull Docker image - run: docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} - - - name: Run container - run: | - docker run -d \ - --name test-container \ - -p 8080:8080 \ - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} - - - name: Test health endpoint (retries) - run: | - set +e - for i in $(seq 1 30); do - code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/v1/health || echo "000") - if [ "$code" = "200" ]; then - echo "✅ Health check passed on attempt $i" - exit 0 - fi - echo "Attempt $i/30: health not ready (code=$code); waiting..." - sleep 2 - done - echo "❌ Health check failed after retries" - docker logs test-container || true - exit 1 - - - name: Check container logs - if: always() - run: docker logs test-container - - - name: Stop container - if: always() - run: docker stop test-container && docker rm test-container - - - name: Create test summary - if: always() - run: | - echo "## 🧪 Docker Image Test Results" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "- **Image**: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }}" >> $GITHUB_STEP_SUMMARY - echo "- **Health Check**: ${{ job.status == 'success' && '✅ Passed' || '❌ Failed' }}" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index c37e3a18..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,353 +0,0 @@ -name: Deploy Documentation to GitHub Pages - -on: - push: - branches: - - main # Deploy docs when pushing to main - paths: - - 'docs/**' # Only run if docs folder changes - - 'README.md' # Or if README changes - - '.github/workflows/docs.yml' # Or if this workflow changes - workflow_dispatch: # Allow manual trigger - -# Sets permissions to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow only one concurrent deployment -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - build: - name: Build Documentation - runs-on: ubuntu-latest - - steps: - # Step 1: Get the code - - name: 📥 Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6 - - # Step 2: Set up Node.js (for building any JS-based doc tools) - - name: 🔧 Set up Node.js - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 - with: - node-version: '24.11.1' - - # Step 3: Create a beautiful docs site structure - - name: 📝 Build documentation site - run: | - # Create output directory - mkdir -p _site - - # Copy all markdown files - cp README.md _site/ - cp -r docs _site/ - - # Create a simple HTML index that looks nice - cat > _site/index.html << 'EOF' - - -
- - -Make your websites easy to reach - No coding required!
-- This documentation will help you get started with Caddy Proxy Manager Plus. - Whether you're a complete beginner or an experienced developer, we've got you covered! -
-Your first setup in just 5 minutes! We'll walk you through everything step by step.
- Read the Guide → -Learn what the app does, how to install it, and see examples of what you can build.
- Read More → -Already using Caddy? Learn how to bring your existing configuration into the app.
- Import Your Configs → -Complete REST API documentation with examples in JavaScript and Python.
- View API Docs → -Understand how data is stored, relationships, and backup strategies.
- View Schema → -Want to help make this better? Learn how to contribute code, docs, or ideas.
- Start Contributing → -Browse all available documentation organized by topic and skill level.
- View Full Index → -- Stuck? Have questions? We're here to help! -
- -