Adds v2 API endpoints for optimized workflow status queries. Implements /workflows/status to fetch latest run per workflow in single query using MAX(id) grouping. Adds /runs/{id}/failure-log endpoint returning structured failure data with job details, failed steps, log tails (last 200 lines), and workflow YAML content. Reduces client-side API calls and processing overhead.
GitCaddy
The AI-native Git platform. Self-hosted, fast, and designed for the age of AI-assisted development.
Table of Contents
- What is GitCaddy?
- Key Features
- V2 API - Modern, AI-Optimized Interface
- AI Context APIs - Repository Intelligence
- Runner Capability Discovery
- Workflow Validation
- Action Compatibility Database
- Core Repository Management
- Collaboration Tools
- CI/CD & Actions
- Package Registry
- Vault System (Pro/Enterprise)
- AI-Powered Features
- Plugin Framework
- Landing Pages & Public Releases
- App Update API (Electron/Squirrel Compatible)
- Release Archive
- Security & Authentication
- Organization Management
- Advanced UI Features
- Installation
- Configuration
- Usage
- GitCaddy Runner
- API Documentation
- Internationalization
- Building from Source
- Contributing
- License
- Acknowledgments
What is GitCaddy?
GitCaddy transforms Git hosting into an AI-ready platform. While traditional Git servers treat AI tools as an afterthought, GitCaddy is built from the ground up with structured APIs, capability discovery, and intelligent context that AI assistants need to write correct code, generate valid CI/CD workflows, and understand your projects deeply.
Key differentiators:
- V2 API - Modern, AI-optimized endpoints with batch operations, streaming, and structured errors
- Runner Capability Discovery - AI tools query runner capabilities before generating workflows
- Action Compatibility Database - Curated compatibility matrix prevents workflow errors
- AI Context APIs - Rich, structured repository and issue intelligence
- Workflow Validation - Pre-flight checks for CI/CD workflows before commit
- Comprehensive Platform - Full-featured Git hosting with collaboration, CI/CD, package registry, and enterprise features
Key Features
V2 API - Modern, AI-Optimized Interface
A complete API redesign focused on AI tool consumption:
| Feature | Description |
|---|---|
| Batch Operations | Fetch up to 100 files in a single request |
| Streaming | NDJSON streams for progressive processing |
| Idempotency | Built-in support for safe request retries |
| Structured Errors | Machine-readable error codes, not just HTTP status |
| Request Tracking | Every request gets a unique ID for debugging |
| Health Checks | Kubernetes-compatible liveness/readiness probes |
| Operation Progress | Server-Sent Events for long-running operations |
GET /api/v2/batch/files # Bulk file retrieval
POST /api/v2/stream/files # NDJSON streaming
GET /api/v2/operations/{id} # Operation status
GET /api/v2/health/ready # Readiness probe
AI Context APIs - Repository Intelligence
Purpose-built endpoints that give AI tools the context they need:
Repository Summary (/api/v2/ai/repo/summary)
{
"name": "my-project",
"primary_language": "Go",
"project_type": "application",
"build_system": "go modules",
"test_framework": "go test",
"suggested_entry_points": ["cmd/main.go", "internal/app/"],
"config_files": ["go.mod", "Makefile", ".gitea/workflows/"],
"language_stats": {"Go": 45000, "YAML": 2000}
}
Repository Navigation (/api/v2/ai/repo/navigation)
- Directory tree with depth control
- Important paths ranked by priority (entry points, tests, docs)
- File type distribution
Issue Context (/api/v2/ai/issue/context)
- Issue details with all comments
- Related issues and code references
- AI hints: category (bug/feature), complexity estimation, suggested files
Runner Capability Discovery
Runners report their capabilities. AI tools query before generating workflows.
Endpoint: GET /api/v2/repos/{owner}/{repo}/actions/runners/capabilities
{
"runners": [
{
"id": 1,
"name": "ubuntu-runner",
"status": "online",
"labels": ["ubuntu-latest", "docker"],
"capabilities": {
"os": "linux",
"arch": "amd64",
"docker": true,
"docker_compose": true,
"shell": ["bash", "sh"],
"tools": {
"node": ["18.19.0", "20.10.0"],
"go": ["1.21.5", "1.22.0"],
"python": ["3.11.6", "3.12.0"]
},
"features": {
"cache": true,
"services": true
}
}
}
],
"platform": {
"type": "gitea",
"version": "1.26.0",
"supported_actions": {
"actions/checkout": {"versions": ["v3", "v4"]},
"actions/setup-node": {"versions": ["v3", "v4"]},
"actions/upload-artifact": {"versions": ["v3"], "notes": "v4 not supported"}
},
"unsupported_features": [
"GitHub-hosted runners",
"OIDC token authentication"
]
},
"workflow_hints": {
"preferred_checkout": "actions/checkout@v4",
"artifact_upload_alternative": "Use Gitea API for artifacts"
}
}
Workflow Validation
Validate workflows before committing. Catch incompatibilities early.
Endpoint: POST /api/v2/repos/{owner}/{repo}/actions/workflows/validate
// Request
{
"content": "name: Build\non: push\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/upload-artifact@v4"
}
// Response
{
"valid": false,
"warnings": [
{
"line": 8,
"action": "actions/upload-artifact@v4",
"severity": "error",
"message": "actions/upload-artifact@v4 is not supported",
"suggestion": "Use actions/upload-artifact@v3"
}
],
"runner_match": [
{
"job": "build",
"runs_on": ["ubuntu-latest"],
"matched_runners": ["ubuntu-runner-1"],
"capabilities_met": true
}
]
}
Action Compatibility Database
Built-in knowledge of GitHub Action compatibility:
| Action | Compatible Versions | Notes |
|---|---|---|
actions/checkout |
v2, v3, v4 | Fully compatible |
actions/setup-node |
v2, v3, v4 | Fully compatible |
actions/setup-go |
v3, v4, v5 | Fully compatible |
actions/setup-python |
v4, v5 | Fully compatible |
actions/cache |
v3, v4 | Fully compatible |
actions/upload-artifact |
v2, v3 | v4 not supported |
actions/download-artifact |
v2, v3 | v4 not supported |
Core Repository Management
- Repository Operations: Create, fork, mirror (push/pull), and migrate repositories from external services
- Branch & Tag Management: Branch protection rules with status checks, approval requirements, and reorderable protection rules
- Code Browsing: Commit history, blame view, diff visualization, and file tree navigation with Vue-based sidebar
- File Operations: Web-based editor for uploading, editing, and deleting files
- Code Search: Full-text search across repository files
- Release Management: Create releases with automatic release notes generation and archive old releases
- Wiki Pages: Markdown-based documentation with full editing capabilities
- Git LFS Support: Large File Storage for binary assets
Collaboration Tools
- Issues: Labels, milestones, assignments, dependencies, and time tracking with real-time stopwatch
- Pull Requests: Code review workflows with approval requirements and multiple merge strategies
- Project Boards: Kanban-style boards with drag-and-drop organization using Sortable.js
- Comments & Reactions: Mention autocomplete with Tribute.js, emoji reactions, and threaded discussions
- Notifications: Comprehensive notification system for repository activity
- Activity Tracking: Contribution graphs and activity heatmaps
CI/CD & Actions
- Workflow Execution: Run GitHub Actions-compatible workflows with monitoring and logs
- Runner Management: Track bandwidth, disk usage, and online/offline status
- Job Queue: Monitor job status and view detailed execution logs
- Secrets & Variables: Encrypted secrets management with CI/CD integration
- Status Checks: Integrate workflow results into branch protection rules
Package Registry
Multi-format package hosting with versioning and dependency management:
- Supported Formats: Alpine, Arch, Cargo, Chef, Composer, Conda, Debian, Docker, Go, Helm, Maven, npm, NuGet, PyPI, RPM, RubyGems, Swift, Vagrant
- Access Controls: Global and per-package permission management
- Version Management: Full version history and dependency tracking
Vault System (Pro/Enterprise)
Enterprise-grade encrypted secrets management:
- Encrypted Storage: Version history for all secrets with rollback capabilities
- Audit Logging: Comprehensive access logs with extended retention for Enterprise tier
- CI/CD Integration: Generate tokens for workflow access to secrets
- Tiered Licensing: Solo, Pro, Team, and Enterprise tiers with different feature sets
AI-Powered Features
GitCaddy integrates with the gitcaddy-ai sidecar service to provide two tiers of AI operations:
Tier 1 - Light Operations (seconds, via gRPC/REST to gitcaddy-ai):
- AI Code Review: Automatic review comments on pull requests when opened or updated
- Issue Auto-Respond: AI generates helpful responses to new issues and @bot mentions
- Issue Triage: Automatic label assignment based on issue content
- Code Explanation: On-demand explanation of code sections
- Documentation Generation: Generate docs for code files
Tier 2 - Agent Operations (minutes, via Actions runners with Claude Code):
- Agent Fix: AI agent clones the repo, investigates issues, creates branches and pull requests
- Triggered by labels (e.g., adding
ai-fixlabel) or manual API call - Sandboxed in existing Actions runner infrastructure
Configuration Cascade: Settings resolve from most specific to least: Repo > Org > System. Each level can override the AI provider, model, and API key.
Built-in Safety:
- Dedicated bot user (
gitcaddy-ai) for clear attribution - Loop prevention: bot-created events never re-trigger AI
- Per-repo rate limiting (ops/hour)
- Admin feature gates for every operation type
- Escalation to staff when AI confidence is low or operations fail
- Full audit log of every AI operation with provider, tokens, duration, and status
Plugin Framework
Extend GitCaddy with external plugins that communicate over gRPC (HTTP/2). The server manages plugin lifecycle, health monitoring, and event dispatch.
- gRPC Protocol: Type-safe plugin contract defined in
plugin.protowith 6 RPCs (Initialize, Shutdown, HealthCheck, GetManifest, OnEvent, HandleHTTP) - Health Monitoring: Automatic periodic health checks with configurable interval; plugins marked offline after 3 consecutive failures
- Auto-Restart: Managed plugins are automatically restarted when they become unresponsive
- Event Dispatch: Plugins subscribe to server events (e.g.,
license:updated) and receive them in real-time - Route Declaration: Plugins declare REST routes in their manifest; the server can proxy HTTP requests to the plugin
- Managed & External Modes: Server can launch and manage plugin processes, or connect to already-running services
See PLUGINS.md for the full plugin development guide.
Landing Pages & Public Releases
Customizable repository landing pages with optional public access for private repositories:
- Custom Domains: Configure custom domains with SSL management
- Templates: Choose from pre-built templates or create custom designs
- Branding: Logos, icons, and theme customization
- Public Access: Expose landing pages and releases for private repos (perfect for commercial software with public downloads)
Configure in .gitea/landing.yaml:
enabled: true
public_landing: true # Allow unauthenticated access to landing page
hero:
title: "My App"
tagline: "The best app ever"
advanced:
public_releases: true # Allow unauthenticated access to releases
API Endpoints (no auth required when enabled):
GET /api/v2/repos/{owner}/{repo}/pages/config # Landing page config
GET /api/v2/repos/{owner}/{repo}/pages/content # Landing page content
GET /api/v2/repos/{owner}/{repo}/releases # List releases
GET /api/v2/repos/{owner}/{repo}/releases/latest # Latest release
App Update API (Electron/Squirrel Compatible)
Purpose-built endpoint for desktop app auto-updates with Squirrel-compatible JSON format.
Endpoint: GET /api/v2/repos/{owner}/{repo}/releases/update
Query Parameters:
| Parameter | Description | Default |
|---|---|---|
version |
Current app version (semver) | Required |
platform |
darwin, windows, linux |
Runtime OS |
arch |
x64, arm64 |
Runtime arch |
channel |
stable, beta, alpha |
stable |
Response (200 OK - update available):
{
"url": "https://git.example.com/owner/repo/releases/download/v1.2.0/App-darwin-arm64.zip",
"name": "v1.2.0",
"notes": "Release notes in markdown...",
"pub_date": "2026-01-10T12:00:00Z",
"platform": {
"size": 45000000,
"releases_url": "https://...", // Windows RELEASES file
"nupkg_url": "https://..." // Windows nupkg
}
}
Response (204 No Content): No update available
Electron Integration:
// In your Electron app
import { autoUpdater } from 'electron'
const version = app.getVersion()
const platform = process.platform
const arch = process.arch === 'arm64' ? 'arm64' : 'x64'
autoUpdater.setFeedURL({
url: `https://git.example.com/api/v2/repos/owner/repo/releases/update?version=${version}&platform=${platform}&arch=${arch}`
})
autoUpdater.checkForUpdates()
Release Archive
Archive old releases without deleting them:
- Toggle archived status via UI or API
- Filter releases by archived state
- Archived releases hidden by default with toggle to show
- Preserves release history for compliance
POST /api/v1/repos/{owner}/{repo}/releases/{id}/archive
DELETE /api/v1/repos/{owner}/{repo}/releases/{id}/archive
GET /api/v1/repos/{owner}/{repo}/releases?archived=false
Security & Authentication
- Two-Factor Authentication: TOTP-based 2FA with recovery codes
- WebAuthn/Hardware Keys: Passkey support with credential management
- SSH/GPG Keys: Key management with parsing and validation
- OAuth2/OpenID Connect: Integration with external identity providers
- LDAP/SAML/SSPI: Enterprise authentication support
- Signed Commits: GPG signature verification
- Branch Protection: Enforce status checks and approval requirements
Organization Management
- Team Management: Granular permissions with role-based access control
- Member Roles: Owner, member, and restricted user types
- Visibility Controls: Public, private, and limited organization visibility
- Pinned Repositories: Feature important projects on organization pages
- License Management: Organization-level licensing for Pro/Enterprise features
Advanced UI Features
- Real-time Updates: EventSource/SharedWorker for synchronized time tracking across tabs
- Interactive Tables: Sortable columns and filterable data
- Math Rendering: LaTeX equations with KaTeX
- Diagram Rendering: Mermaid diagrams in isolated iframes
- Code Block Enhancements: Copy-to-clipboard buttons and syntax highlighting
- Task Lists: Interactive checkboxes in Markdown
- Terminal Playback: Asciinema recording playback
- Accessibility: ARIA attributes, keyboard navigation, and screen reader support
- Responsive Design: Mobile-friendly interface with overflow menus
- Toast Notifications: Non-intrusive status messages with Toastify.js
- Tooltips: Context-sensitive help with Tippy.js
- Image Gallery: Project showcase capabilities
Installation
From Binary
Download from Releases:
# Linux (amd64)
curl -L -o gitcaddy-server https://git.marketally.com/gitcaddy/gitcaddy-server/releases/latest/download/gitcaddy-server-linux-amd64
chmod +x gitcaddy-server
./gitcaddy-server web
# macOS (arm64)
curl -L -o gitcaddy-server https://git.marketally.com/gitcaddy/gitcaddy-server/releases/latest/download/gitcaddy-server-darwin-arm64
chmod +x gitcaddy-server
./gitcaddy-server web
# Windows (amd64)
# Download gitcaddy-server-windows-amd64.exe and run:
gitcaddy-server.exe web
The server will start on http://localhost:3000 by default. On first run, you'll be redirected to the installation wizard.
From Source
# Clone the repository
git clone https://git.marketally.com/gitcaddy/gitcaddy-server.git
cd gitcaddy-server
# Build with SQLite support
TAGS="bindata sqlite sqlite_unlock_notify" make build
# Run the server
./gitcaddy-server web
Requirements:
- Go 1.24+ (see
go.mod) - Node.js 22.6+ (for frontend)
- Make
Docker
# Run with Docker
docker run -d \
--name gitcaddy \
-p 3000:3000 \
-v ./data:/data \
gitcaddy/gitea:latest
# Or use Docker Compose
version: "3"
services:
gitcaddy:
image: gitcaddy/gitea:latest
ports:
- "3000:3000"
volumes:
- ./data:/data
restart: unless-stopped
Configuration
Database Setup
GitCaddy supports multiple database backends. Configure during installation or in app.ini:
Supported Databases:
- SQLite (default, no additional setup required)
- MySQL 5.7+ / MariaDB 10.2+
- PostgreSQL 10+
- MSSQL 2008+
Example MySQL Configuration:
[database]
DB_TYPE = mysql
HOST = 127.0.0.1:3306
NAME = gitcaddy
USER = gitcaddy
PASSWD = your_password
Example PostgreSQL Configuration:
[database]
DB_TYPE = postgres
HOST = 127.0.0.1:5432
NAME = gitcaddy
USER = gitcaddy
PASSWD = your_password
SSL_MODE = disable
AI Features Configuration
AI features require the gitcaddy-ai sidecar service running alongside your GitCaddy instance. See the gitcaddy-ai README for deployment instructions (Docker Compose recommended).
1. Enable AI in app.ini:
[ai]
; Master switch — nothing AI-related runs unless this is true
ENABLED = true
; gitcaddy-ai sidecar address (REST port)
SERVICE_URL = localhost:5050
SERVICE_TOKEN =
; Connection settings
TIMEOUT = 30s
MAX_RETRIES = 3
; Default provider/model (fallback when org/repo don't override)
DEFAULT_PROVIDER = claude ; claude, openai, or gemini
DEFAULT_MODEL = claude-sonnet-4-20250514
; System API keys (used when org/repo don't provide their own)
CLAUDE_API_KEY = sk-ant-...
OPENAI_API_KEY =
GEMINI_API_KEY =
; Rate limiting (per repo)
MAX_OPERATIONS_PER_HOUR = 100
MAX_TOKENS_PER_OPERATION = 8192
; Feature gates — admin controls what's available instance-wide
ENABLE_CODE_REVIEW = true ; Tier 1: PR review
ENABLE_ISSUE_TRIAGE = true ; Tier 1: auto-label issues
ENABLE_DOC_GEN = true ; Tier 1: documentation generation
ENABLE_EXPLAIN_CODE = true ; Tier 1: code explanation
ENABLE_CHAT = true ; Tier 1: chat interface
ALLOW_AUTO_RESPOND = true ; Tier 1: auto-respond to issues
ALLOW_AUTO_REVIEW = true ; Tier 1: auto-review PRs
ALLOW_AGENT_MODE = false ; Tier 2: agent fix (off by default, requires runner setup)
; Content limits
MAX_FILE_SIZE_KB = 500
MAX_DIFF_LINES = 5000
; Bot user (created automatically on first startup)
BOT_USER_NAME = gitcaddy-ai
2. Configure org-level settings (optional):
Organization admins can override the provider, model, and API key for all repos in the org. This is done via:
- Web UI:
/{org}/settings/ai - API:
PUT /api/v2/orgs/{org}/ai/settings
Org settings include:
- Provider & model selection
- API key (encrypted at rest)
- Rate limits (max ops/hour)
- Allowed operations list
- Agent mode toggle
3. Enable AI on a repository:
Repository admins enable AI and choose which operations to activate. This is done via:
- Web UI:
/{owner}/{repo}/settings/ai - API:
PUT /api/v2/repos/{owner}/{repo}/ai/settings
Repo settings include:
- Enable/Disable: Toggles the AI unit on the repo
- Tier 1 Operations: Auto-respond to issues, auto-review PRs, auto-triage issues, auto-inspect workflows
- Tier 2 Agent Mode: Enable agent fix, configure trigger labels (e.g.,
ai-fix), set max run time - Escalation: Enable staff escalation on failure, set escalation label and team
- Provider Override: Override org/system provider and model for this repo
- Custom Instructions: System instructions, review instructions, issue response instructions
4. Set up Tier 2 agent runners (optional):
For agent mode (AI that creates branches and PRs), you need an Actions runner with Claude Code installed:
- Register a runner with the
ai-runnerlabel - Install the Claude Code CLI on the runner
- Place the agent workflow file in your repo at
.gitea/workflows/ai-agent.yml(a template is available via the API) - Set the
AI_API_KEYsecret on the repo or org
When a trigger label is added to an issue (or an agent fix is requested via API), the server dispatches the workflow, the runner clones the repo, runs Claude Code headless, and creates a PR with the proposed fix.
Plugin Framework Configuration
The plugin framework allows external services (like the AI sidecar) to register with GitCaddy for lifecycle management, health monitoring, and event dispatch. Plugins communicate over gRPC (HTTP/2) using the protocol defined in modules/plugins/pluginv1/plugin.proto.
1. Enable the plugin framework in app.ini:
[plugins]
; Master switch for the plugin framework
ENABLED = true
; Directory for plugin data
PATH = data/plugins
; How often to health-check external plugins
HEALTH_CHECK_INTERVAL = 30s
2. Register external plugins:
Each plugin gets its own [plugins.<name>] section:
[plugins.gitcaddy-ai]
ENABLED = true
; Address of the plugin's gRPC endpoint (cleartext HTTP/2)
ADDRESS = localhost:5000
; Health check timeout
HEALTH_TIMEOUT = 5s
; Events the plugin subscribes to (comma-separated)
SUBSCRIBED_EVENTS = license:updated
Managed vs External Mode:
| Mode | Configuration | Use Case |
|---|---|---|
| External | ADDRESS only |
Plugin runs independently (Docker, systemd, sidecar) |
| Managed | BINARY + ARGS |
Server launches and manages the plugin process |
Managed mode example:
[plugins.my-plugin]
ENABLED = true
BINARY = /usr/local/bin/my-plugin
ARGS = --port 5001
ADDRESS = localhost:5001
HEALTH_TIMEOUT = 5s
When a managed plugin becomes unresponsive (3 consecutive health check failures), the server automatically restarts its process.
See PLUGINS.md for the full plugin development guide.
V2 API Configuration
[api]
; Enable V2 API (enabled by default)
ENABLE_V2_API = true
; Max files in batch request
MAX_BATCH_SIZE = 100
; Enable AI context endpoints
ENABLE_AI_CONTEXT = true
Authentication Sources
Configure external authentication through the admin dashboard or app.ini:
OAuth2 Providers:
- GitHub, GitLab, Gitea, Bitbucket
- Google, Microsoft, Discord, Twitter
- Generic OAuth2 providers
LDAP/Active Directory:
[auth.ldap]
ENABLED = true
HOST = ldap.example.com
PORT = 389
BIND_DN = cn=admin,dc=example,dc=com
BIND_PASSWORD = password
USER_BASE = ou=users,dc=example,dc=com
USER_FILTER = (uid=%s)
SAML 2.0: Configure through the admin dashboard with your identity provider's metadata.
Email/SMTP Setup
Configure email notifications in app.ini. Email is required for account registration, password resets, notification delivery, and blog guest comment verification (anonymous commenters receive a 6-digit code via email to verify their identity).
[mailer]
ENABLED = true
FROM = noreply@your-instance.com
PROTOCOL = smtp+starttls
SMTP_ADDR = smtp.gmail.com
SMTP_PORT = 587
USER = your-email@gmail.com
PASSWD = your-app-password
Supported protocols: smtp+starttls (recommended), smtps, smtp, sendmail
Common provider examples:
| Provider | SMTP_ADDR | SMTP_PORT | PROTOCOL |
|---|---|---|---|
| Gmail | smtp.gmail.com | 587 | smtp+starttls |
| Office 365 | smtp.office365.com | 587 | smtp+starttls |
| Amazon SES | email-smtp.us-east-1.amazonaws.com | 587 | smtp+starttls |
| Mailgun | smtp.mailgun.org | 587 | smtp+starttls |
| SendGrid | smtp.sendgrid.net | 587 | smtp+starttls |
Note: Gmail requires an App Password (not your regular password) when 2FA is enabled. Amazon SES requires SMTP credentials generated from the SES console.
Unsplash Integration
Enable Unsplash image search for repository social card backgrounds (Media Kit). This allows repository admins to search and select high-quality background images directly from Unsplash.
[unsplash]
; Enable Unsplash integration for Media Kit background images
ENABLED = true
; Unsplash API access key (get one at https://unsplash.com/developers)
ACCESS_KEY = your_unsplash_access_key
To obtain an access key:
- Create an account at unsplash.com/developers
- Create a new application
- Copy the Access Key (the Secret Key is not needed)
When enabled, repository admins can search Unsplash from Settings > Media Kit when using the "Background Image" social card style. Attribution is handled automatically per Unsplash API guidelines.
Monetize / Subscriptions
Gate repository code access (source view, clone, archive downloads) behind paid subscriptions. Issues and releases remain accessible. Supports monthly, yearly, and lifetime pricing tiers with Stripe and PayPal payment providers.
1. Enable the feature in app.ini:
[monetize]
ENABLED = true
2. Configure payment providers in Site Administration > Monetize:
- Enter your Stripe secret key, publishable key, and webhook secret
- Enter your PayPal client ID, client secret, and webhook ID
- Enable each provider individually
3. Enable subscriptions per repository in Repository Settings > Subscriptions > General:
- Toggle "Enable Subscriptions" for the repository
4. Create subscription products in Repository Settings > Subscriptions > Products:
- Add monthly, yearly, or lifetime products with pricing
- Optionally link Stripe Price IDs and PayPal Plan IDs for recurring billing
How it works:
- Users without an active subscription see a subscribe page (HTTP 402) when accessing gated code
- Repository owners, admins, collaborators with write access, and site admins bypass the paywall
- Webhooks from Stripe and PayPal automatically update subscription status (renewals, cancellations, failures)
- The subscribe page at
/{owner}/{repo}/subscribepresents product cards with embedded Stripe Elements and PayPal buttons
Webhook endpoints (configure these in your Stripe/PayPal dashboards):
POST /-/monetize/webhooks/stripe
POST /-/monetize/webhooks/paypal
Usage
Repository Operations
Creating Repositories:
- Click the "+" icon in the top navigation
- Select "New Repository"
- Choose a template (optional) or start from scratch
- Configure repository settings (visibility, README, .gitignore, license)
Forking:
- Navigate to any repository
- Click "Fork" in the top-right corner
- Select the destination organization or user
Mirroring:
- Create a new repository
- Enable "This repository is a mirror"
- Configure pull/push mirror settings
- Set synchronization schedule
Migration:
- Click "+" → "New Migration"
- Select source platform (GitHub, GitLab, Gitea, Gogs)
- Provide repository URL and credentials
- Choose items to migrate (issues, PRs, releases, wiki)
Project Management
Issues:
- Create issues with labels, milestones, and assignments
- Add dependencies between issues
- Track time with the built-in stopwatch (synchronized across browser tabs)
- Use mentions (@username) with autocomplete
- Add reactions and threaded comments
Pull Requests:
- Create PRs from branches or forks
- Request reviews from team members
- View inline diff with syntax highlighting
- Approve/request changes with review comments
- Merge with strategies: merge commit, squash, or rebase
Project Boards:
- Create Kanban boards with custom columns
- Drag and drop issues/PRs between columns
- Filter by labels, milestones, or assignees
- Track progress with visual indicators
CI/CD Workflows
Creating Workflows:
Create .gitea/workflows/build.yml:
name: Build and Test
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install
- run: npm test
Validating Before Commit:
# Use the validation API
curl -X POST https://your-instance.com/api/v2/repos/owner/repo/actions/workflows/validate \
-H "Authorization: token YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "..."}'
Monitoring Workflows:
- View workflow runs in the "Actions" tab
- Check runner status and capabilities
- View job logs in real-time
- Re-run failed jobs
Package Registry Usage
Publishing npm Packages:
# Configure registry
npm config set registry https://your-instance.com/api/packages/owner/npm/
# Authenticate
npm login --registry=https://your-instance.com/api/packages/owner/npm/
# Publish
npm publish
Publishing Docker Images:
# Login
docker login your-instance.com
# Tag and push
docker tag myimage:latest your-instance.com/owner/myimage:latest
docker push your-instance.com/owner/myimage:latest
Other Formats: Refer to the package registry documentation for Maven, PyPI, Cargo, Helm, and other formats.
Vault Usage (Pro/Enterprise)
Creating Secrets:
- Navigate to repository settings → Vault
- Click "New Secret"
- Enter key-value pairs
- Secrets are automatically encrypted and versioned
Using in Workflows:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
run: ./deploy.sh
Viewing Audit Logs:
- Access audit logs in the Vault section
- Filter by user, action, and date range
- Export logs for compliance (Enterprise tier)
Rolling Back Secrets:
- View secret history
- Select a previous version
- Click "Restore"
Landing Pages Configuration
Creating a Landing Page:
- Create
.gitea/landing.yamlin your repository:
enabled: true
public_landing: true # For private repos with public landing page
hero:
title: "My Amazing Project"
tagline: "The best solution for your needs"
cta_text: "Download Now"
cta_link: "/releases/latest"
features:
- title: "Fast"
description: "Lightning-fast performance"
icon: "⚡"
- title: "Secure"
description: "Enterprise-grade security"
icon: "🔒"
gallery:
- image: "screenshot1.png"
caption: "Main interface"
- image: "screenshot2.png"
caption: "Advanced features"
advanced:
custom_domain: "myproject.com"
ssl_enabled: true
public_releases: true
- Commit and push the file
- Access your landing page at
https://your-instance.com/owner/repo/pages
AI Features Usage
Automatic Operations (Event-Driven)
Once AI is enabled on a repo with the desired operations toggled on, these fire automatically:
| Event | Operations Triggered | Tier |
|---|---|---|
| New issue created | Auto-respond + Auto-triage | 1 |
Comment mentions @gitcaddy-ai |
Auto-respond | 1 |
| Pull request opened | Auto-review | 1 |
| PR branch updated (push) | Auto-review (re-review) | 1 |
| Trigger label added to issue | Agent fix | 2 |
All operations are queued asynchronously and processed by the AI service. The bot user posts comments/reviews on the issue or PR with the results.
Manual API Triggers
Trigger AI operations on demand via the v2 API:
# Trigger AI code review on a pull request
curl -X POST https://your-instance.com/api/v2/repos/owner/repo/ai/review/1 \
-H "Authorization: token YOUR_TOKEN"
# Trigger AI response to an issue
curl -X POST https://your-instance.com/api/v2/repos/owner/repo/ai/respond/42 \
-H "Authorization: token YOUR_TOKEN"
# Trigger AI triage on an issue
curl -X POST https://your-instance.com/api/v2/repos/owner/repo/ai/triage/42 \
-H "Authorization: token YOUR_TOKEN"
# Explain code in a file
curl -X POST https://your-instance.com/api/v2/repos/owner/repo/ai/explain \
-H "Authorization: token YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"file_path": "main.go", "start_line": 10, "end_line": 50, "question": "What does this function do?"}'
# Trigger Tier 2 agent fix (creates a PR)
curl -X POST https://your-instance.com/api/v2/repos/owner/repo/ai/fix/42 \
-H "Authorization: token YOUR_TOKEN"
All trigger endpoints return 202 Accepted with the queued operation details.
Viewing AI Operation History
Every AI operation is logged with full audit details:
# List operations for a repo (paginated, filterable)
curl "https://your-instance.com/api/v2/repos/owner/repo/ai/operations?status=success&tier=1&page=1" \
-H "Authorization: token YOUR_TOKEN"
# Get a single operation's details
curl https://your-instance.com/api/v2/repos/owner/repo/ai/operations/123 \
-H "Authorization: token YOUR_TOKEN"
# Global operation log (site admin only)
curl https://your-instance.com/api/v2/admin/ai/operations \
-H "Authorization: token YOUR_TOKEN"
Each operation log entry includes: operation type, tier, trigger event, provider, model, input/output tokens, duration, status (success/failed/escalated), and the resulting comment or Actions run ID.
Escalation
When an AI operation fails or returns low confidence, and the repo has escalation configured:
- The configured escalation label (e.g.,
needs-human-review) is added to the issue - The bot posts a summary comment explaining what it attempted and why it's escalating
- If an escalation team is configured, a team member is assigned
AI Context APIs (for External AI Tools)
These endpoints provide structured context to external AI tools (IDE plugins, MCP servers, etc.):
# Get repository summary (languages, build system, entry points)
curl -X POST https://your-instance.com/api/v2/ai/repo/summary \
-H "Authorization: token YOUR_TOKEN" \
-d '{"owner": "owner", "repo": "repo"}'
# Get issue context (details, comments, complexity hints)
curl -X POST https://your-instance.com/api/v2/ai/issue/context \
-H "Authorization: token YOUR_TOKEN" \
-d '{"owner": "owner", "repo": "repo", "issue": 123}'
# Get repository navigation (directory tree, important paths)
curl -X POST https://your-instance.com/api/v2/ai/repo/navigation \
-H "Authorization: token YOUR_TOKEN" \
-d '{"owner": "owner", "repo": "repo", "depth": 3}'
GitCaddy Runner
For full capability reporting and optimal workflow execution, use the GitCaddy act_runner:
# Download
curl -L -o act_runner https://git.marketally.com/gitcaddy/act_runner/releases/latest/download/act_runner-linux-amd64
chmod +x act_runner
# Register with your GitCaddy instance
./act_runner register \
--instance https://your-instance.com \
--token YOUR_REGISTRATION_TOKEN \
--name my-runner \
--labels ubuntu-latest,docker
# Run the runner daemon
./act_runner daemon
Automatic Capability Detection:
The runner automatically detects and reports:
- Operating system and architecture
- Docker/Podman availability and version
- Docker Compose support
- Installed tools and their versions:
- Node.js
- Go
- Python
- Java
- .NET
- Rust
- Ruby
- PHP
- Available shells (bash, sh, pwsh, cmd)
- Cache support
- Service containers support
Viewing Runner Capabilities:
Access runner capabilities through the API or UI:
curl https://your-instance.com/api/v2/repos/owner/repo/actions/runners/capabilities \
-H "Authorization: token YOUR_TOKEN"
API Documentation
GitCaddy provides comprehensive API documentation:
- Interactive Explorer: Visit
/api/v2/docson your instance for the Scalar API explorer - OpenAPI Specification: Download from
/api/v2/swagger.json - Legacy API: V1 API documentation available at
/api/swagger
Authentication:
All API endpoints require authentication via token:
# Create a token in Settings → Applications → Generate New Token
# Use in requests
curl https://your-instance.com/api/v2/repos/owner/repo \
-H "Authorization: token YOUR_TOKEN"
Common API Operations:
# List repositories
GET /api/v2/user/repos
# Get repository details
GET /api/v2/repos/{owner}/{repo}
# Create an issue
POST /api/v2/repos/{owner}/{repo}/issues
# List pull requests
GET /api/v2/repos/{owner}/{repo}/pulls
# Get runner capabilities
GET /api/v2/repos/{owner}/{repo}/actions/runners/capabilities
# Validate workflow
POST /api/v2/repos/{owner}/{repo}/actions/workflows/validate
# Batch file retrieval
GET /api/v2/batch/files?paths=file1.go,file2.go&owner=owner&repo=repo
# Stream files (NDJSON)
POST /api/v2/stream/files
# AI: Get/update repo AI settings
GET /api/v2/repos/{owner}/{repo}/ai/settings
PUT /api/v2/repos/{owner}/{repo}/ai/settings
# AI: Trigger operations
POST /api/v2/repos/{owner}/{repo}/ai/review/{pull}
POST /api/v2/repos/{owner}/{repo}/ai/respond/{issue}
POST /api/v2/repos/{owner}/{repo}/ai/triage/{issue}
POST /api/v2/repos/{owner}/{repo}/ai/explain
POST /api/v2/repos/{owner}/{repo}/ai/fix/{issue}
# AI: Operation audit log
GET /api/v2/repos/{owner}/{repo}/ai/operations
GET /api/v2/repos/{owner}/{repo}/ai/operations/{id}
# AI: Org settings
GET /api/v2/orgs/{org}/ai/settings
PUT /api/v2/orgs/{org}/ai/settings
# AI: Admin
GET /api/v2/admin/ai/status
GET /api/v2/admin/ai/operations
Internationalization
GitCaddy supports 12+ languages with full UI translation:
Supported Languages:
- German (de-DE)
- English (en-US)
- Irish (ga-IE)
- Hindi (hi-IN)
- Hungarian (hu-HU)
- Indonesian (id-ID)
- Icelandic (is-IS)
- Italian (it-IT)
- Dutch (nl-NL)
- Polish (pl-PL)
- Brazilian Portuguese (pt-BR)
- Portuguese (pt-PT)
Changing Language:
- Click your avatar in the top-right
- Select "Settings"
- Choose "Language" from the dropdown
- Save changes
Contributing Translations:
Translations are stored in JSON files at options/locale/. To contribute:
- Copy an existing locale file
- Translate all strings
- Submit a pull request
Building from Source
Requirements:
- Go 1.24+ (see
go.modfor exact version) - Node.js 22.6+
- Make
- Git
Build Commands:
# Clone the repository
git clone https://git.marketally.com/gitcaddy/gitcaddy-server.git
cd gitcaddy-server
# Full build (backend + frontend)
TAGS="bindata sqlite sqlite_unlock_notify" make build
# Backend only
make backend
# Frontend only
make frontend
# Run tests
make test
# Run with live reload (development)
make watch
# Generate API documentation
make generate-swagger
Build Tags:
bindata- Embed static assets into binarysqlite- Enable SQLite supportsqlite_unlock_notify- Enable SQLite unlock notificationspam- Enable PAM authenticationgogit- Use pure Go git implementation
Development Setup:
# Install frontend dependencies
npm install
# Run frontend in development mode
npm run dev
# Run backend with hot reload
make watch-backend
# Run tests with coverage
make test-coverage
Contributing
We welcome contributions! Here's how to get started:
- Fork the repository on GitCaddy
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes with clear commit messages
- Run tests:
make test - Run linters:
make lint - Submit a pull request with a clear description
Code Style:
- Go: Follow standard Go conventions (
gofmt,golint) - TypeScript: Use ESLint configuration in the repository
- Commit messages: Use conventional commits format
Testing:
- Write unit tests for new features
- Ensure all tests pass before submitting
- Add integration tests for API changes
Documentation:
- Update README.md for user-facing changes
- Add API documentation for new endpoints
- Include code comments for complex logic
License
MIT License - see LICENSE for details.
Acknowledgments
GitCaddy is a fork of Gitea, the open-source self-hosted Git service. We thank the Gitea team and all contributors for building the foundation that makes GitCaddy possible.
- Gitea Project - The upstream project
- Claude Code - AI-assisted development by Anthropic
- Gitea Contributors - All the amazing contributors
Related Projects:
| Project | Description |
|---|---|
| gitcaddy/act_runner | Runner with automatic capability detection |
| gitcaddy/gitcaddy-ai | AI sidecar service (.NET 9, gRPC/REST) for code review, triage, and more |
| gitcaddy/actions-proto-go | Protocol buffer definitions for Actions |
Support:
- Documentation: https://docs.gitcaddy.com
- Issues: Report bugs and request features on our issue tracker
- Community: Join discussions in our repository
GitCaddy Users Guide
A comprehensive guide to using GitCaddy, a self-hosted Git repository management platform with AI capabilities, encrypted secrets management, and enterprise features.
Table of Contents
- Introduction
- Getting Started
- Basic Repository Operations
- Collaboration Workflows
- Wiki Documentation
- CI/CD with GitCaddy Actions
- Vault: Encrypted Secrets Management
- Package Registry
- AI-Powered Features
- Organizations and Teams
- Landing Pages and Custom Domains
- Authentication and Security
- Customization and Settings
- Tips and Best Practices
- Troubleshooting
Introduction
GitCaddy is a powerful, self-hosted Git repository management platform that provides a complete solution for version control, issue tracking, CI/CD workflows, package registry, and team collaboration. Built as an enhanced fork of Gitea, GitCaddy adds enterprise features including:
- AI-powered code review and issue triage
- Vault encrypted secrets management with audit logging
- Package registry supporting npm, Maven, Docker, PyPI, Go, Cargo, NuGet, and more
- Custom landing pages with SSL/TLS support
- Comprehensive internationalization with 18+ supported languages
- GitCaddy Actions for CI/CD automation
- Advanced collaboration tools including project boards, wikis, and time tracking
This guide will walk you through everything you need to know to effectively use GitCaddy, from initial setup to advanced workflows.
Getting Started
Prerequisites
Before installing GitCaddy, ensure you have the following:
- Go runtime (version 1.18 or higher)
- Node.js and npm (for building frontend assets)
- Git (version 2.0 or higher)
- Database: PostgreSQL, MySQL, SQLite, or MSSQL
- Operating System: Linux, macOS, or Windows
Installation
Follow these steps to install GitCaddy on your server:
1. Clone the Repository
git clone https://github.com/your-org/gitcaddy.git
cd gitcaddy
2. Build the Backend
# Install Go dependencies
go mod download
# Build the GitCaddy binary
go build -o gitcaddy
3. Build the Frontend
# Install Node.js dependencies
npm install
# Build frontend assets
npm run build
4. Configure the Database
Create a configuration file custom/conf/app.ini with your database settings:
[database]
DB_TYPE = postgres
HOST = localhost:5432
NAME = gitcaddy
USER = gitcaddy_user
PASSWD = your_secure_password
Supported database types: postgres, mysql, sqlite3, mssql
5. Start GitCaddy
./gitcaddy web
By default, GitCaddy runs on port 3000. Access it at http://localhost:3000
First-Time Setup
When you first access GitCaddy, you'll be guided through a web-based installation wizard:
- Database Configuration: Verify or adjust database connection settings
- General Settings: Configure site title, domain, and SSH/HTTP ports
- Administrator Account: Create your admin user account
- Optional Settings: Configure email, server paths, and additional features
- Install: Click "Install GitCaddy" to complete setup
After installation, you'll be redirected to your dashboard where you can start creating repositories and inviting users.
Basic Repository Operations
Creating a Repository
To create a new repository:
-
Click the "+" icon in the top navigation bar
-
Select "New Repository"
-
Fill in the repository details:
- Owner: Select your user or an organization
- Repository Name: Choose a unique name
- Description: Optional description of your project
- Visibility: Public or Private
- Initialize Repository: Optionally add README, .gitignore, and license
- Template: Search for and select a repository template
-
Click "Create Repository"
Example: Creating a Node.js project repository
Owner: myusername
Repository Name: my-nodejs-app
Description: A sample Node.js application
Visibility: Private
✓ Initialize with README
.gitignore: Node
License: MIT License
Cloning and Pushing Code
After creating a repository, clone it to your local machine:
# Clone via HTTPS
git clone https://gitcaddy.example.com/username/my-nodejs-app.git
# Or clone via SSH
git clone git@gitcaddy.example.com:username/my-nodejs-app.git
Add files and push your first commit:
cd my-nodejs-app
echo "# My Node.js App" > README.md
git add README.md
git commit -m "Initial commit"
git push origin main
Managing Branches and Tags
Creating a Branch
# Create and switch to a new branch
git checkout -b feature/new-feature
# Push the branch to GitCaddy
git push origin feature/new-feature
In the GitCaddy web interface:
- Navigate to your repository
- Click the branch dropdown (usually shows "main")
- Type a new branch name and click "Create branch"
Branch Protection Rules
Protect important branches from direct pushes:
- Go to Settings → Branches
- Click "Add Rule"
- Configure protection settings:
- Require pull request reviews
- Require status checks to pass
- Restrict who can push
- Enable force push protection
Creating Tags
# Create an annotated tag
git tag -a v1.0.0 -m "Release version 1.0.0"
# Push tags to GitCaddy
git push origin --tags
File Operations
GitCaddy provides a web-based file editor for quick changes:
- Navigate to a file in your repository
- Click the pencil icon to edit
- Make your changes in the markdown-aware editor
- Add a commit message
- Choose to commit directly or create a new branch
- Click "Commit Changes"
Uploading Files:
- Navigate to the target directory
- Click "Upload file"
- Drag and drop files or click to browse
- Add a commit message and commit
Deleting Files:
- Navigate to the file
- Click the trash icon
- Confirm deletion with a commit message
Collaboration Workflows
Working with Issues
Issues are the foundation of project tracking in GitCaddy. They support rich features including labels, milestones, assignments, time tracking, and dependencies.
Creating an Issue
-
Navigate to your repository
-
Click the "Issues" tab
-
Click "New Issue"
-
Fill in the details:
- Title: Brief description of the issue
- Description: Detailed explanation using markdown
- Labels: Categorize the issue (bug, enhancement, question, etc.)
- Milestone: Associate with a project milestone
- Assignees: Assign team members
- Projects: Add to a project board
-
Click "Create Issue"
Example Issue:
Title: Add user authentication to API
Description:
## Problem
The API currently lacks authentication, allowing unauthorized access.
## Proposed Solution
Implement JWT-based authentication with the following endpoints:
- POST /api/auth/login
- POST /api/auth/register
- POST /api/auth/refresh
## Acceptance Criteria
- [ ] JWT tokens are generated on successful login
- [ ] Protected endpoints validate tokens
- [ ] Refresh token mechanism is implemented
- [ ] Unit tests cover all auth flows
Labels: enhancement, security
Milestone: v2.0.0
Assignees: @developer1, @developer2
Time Tracking
Track time spent on issues:
- Open an issue
- In the sidebar, find "Time Tracking"
- Click "Add Time" and enter hours/minutes
- View total time spent and estimates
Issue Dependencies
Create dependencies between issues:
- Open an issue
- In the description or comments, reference another issue:
Depends on #123 - GitCaddy automatically creates a dependency link
- The dependent issue cannot be closed until dependencies are resolved
Pull Request Workflow
Pull requests (PRs) enable code review and collaborative development.
Creating a Pull Request
-
Push your feature branch to GitCaddy
-
Navigate to the repository
-
Click "New Pull Request"
-
Select the base branch (e.g.,
main) and compare branch (e.g.,feature/new-feature) -
Review the diff visualization
-
Fill in PR details:
- Title: Descriptive title
- Description: Explain changes, link related issues
- Reviewers: Request reviews from team members
- Labels, Milestone, Assignees: Same as issues
-
Click "Create Pull Request"
Example PR Description:
## Changes
This PR implements user authentication for the API as described in #45.
## Implementation Details
- Added JWT middleware for token validation
- Created auth controller with login/register/refresh endpoints
- Implemented password hashing with bcrypt
- Added comprehensive unit tests (95% coverage)
## Testing
- All existing tests pass
- New tests cover authentication flows
- Manual testing completed on staging environment
Closes #45
Reviewing Pull Requests
As a reviewer:
-
Open the pull request
-
Navigate to the "Files changed" tab
-
Review the diff:
- Click on a line number to add inline comments
- Suggest specific code changes
- Mark files as reviewed
-
Submit your review:
- Comment: General feedback without approval
- Approve: Approve the changes
- Request Changes: Block merging until issues are addressed
Merging Pull Requests
Once approved and status checks pass:
-
Click the "Merge Pull Request" button
-
Choose a merge strategy:
- Create a merge commit: Preserves all commits with a merge commit
- Squash and merge: Combines all commits into one
- Rebase and merge: Replays commits on top of base branch
-
Confirm the merge
-
Optionally delete the feature branch
Code Reviews
GitCaddy supports comprehensive code review features:
- Inline comments: Comment on specific lines of code
- Suggestion blocks: Propose code changes that can be committed directly
- Review threads: Discussions can be marked as resolved
- Status checks: Automated checks must pass before merging
- Required approvals: Enforce minimum number of approvals
Making a code suggestion:
```suggestion
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
### Project Boards
Organize work using Kanban-style project boards:
1. Navigate to your repository
2. Click the **"Projects"** tab
3. Click **"New Project"**
4. Choose a template or start blank
5. Create columns (e.g., "To Do", "In Progress", "Done")
6. Add issues and pull requests to columns
7. Drag and drop cards between columns
**Best Practice**: Use automation rules to move cards automatically based on issue/PR status.
---
## Wiki Documentation
Every repository includes a wiki for documentation.
### Creating Wiki Pages
1. Navigate to the **"Wiki"** tab in your repository
2. Click **"New Page"**
3. Enter a page title
4. Write content using the EasyMDE markdown editor with live preview
5. Click **"Save Page"**
### Wiki Features
- **Markdown support**: Full markdown syntax including tables, code blocks, and images
- **Mermaid diagrams**: Embed flowcharts, sequence diagrams, and more
- **Math formulas**: Use KaTeX for mathematical notation
- **Page hierarchy**: Organize pages with forward slashes (e.g., `Getting Started/Installation`)
- **History**: View page revisions and revert changes
- **Search**: Full-text search across all wiki pages
**Example Wiki Page:**
```markdown
# API Documentation
## Authentication
All API requests require a JWT token in the Authorization header:
```http
GET /api/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Endpoints
GET /api/users
Returns a list of users.
Response:
{
"users": [
{"id": 1, "username": "alice"},
{"id": 2, "username": "bob"}
]
}
Rate Limiting
API requests are limited to 100 requests per hour per user.
---
## CI/CD with GitCaddy Actions
GitCaddy Actions provides integrated CI/CD automation similar to GitHub Actions.
### Creating Workflows
Workflows are defined in YAML files stored in `.gitea/workflows/` directory.
#### Example: Node.js Test Workflow
Create `.gitea/workflows/test.yml`:
```yaml
name: Node.js Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14, 16, 18]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Upload coverage
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: coverage/
Commit and push this file to trigger the workflow.
Managing Runners
Runners execute your workflow jobs. GitCaddy supports self-hosted runners.
Registering a Runner
- Navigate to Settings → Actions → Runners
- Click "Add Runner"
- Follow the instructions to download and configure the runner on your machine:
# Download runner
wget https://gitcaddy.example.com/actions/runner/download
# Extract and configure
./config.sh --url https://gitcaddy.example.com --token YOUR_RUNNER_TOKEN
# Start the runner
./run.sh
Monitoring Runners
- View runner status (online/offline) in the Runners page
- Check runner tasks and job history
- Run bandwidth tests to verify connectivity
Secrets and Variables
Store sensitive data like API keys and passwords securely.
Adding Secrets
- Navigate to Settings → Secrets and Variables → Actions
- Click "New repository secret"
- Enter a name (e.g.,
API_KEY) and value - Click "Add secret"
Using Secrets in Workflows
steps:
- name: Deploy to production
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Security Note: Secrets are encrypted and never exposed in logs.
Vault: Encrypted Secrets Management
Vault is an enterprise feature providing advanced encrypted secrets management with version history and audit logging.
Creating Secrets
-
Navigate to Settings → Vault
-
Click "New Secret"
-
Enter secret details:
- Key: Secret identifier (e.g.,
production-db-password) - Value: Secret content (automatically encrypted)
- Description: Optional description
- Key: Secret identifier (e.g.,
-
Click "Create Secret"
Using Secrets in CI/CD
Vault secrets can be accessed in workflows using access tokens.
Generate an Access Token
-
In Vault settings, click "Access Tokens"
-
Click "Generate Token"
-
Configure token permissions:
- Scope: Select specific secrets or all secrets
- Expiration: Set token lifetime
- Permissions: Read-only or read-write
-
Copy the generated token (shown only once)
Use Token in Workflow
steps:
- name: Fetch database credentials
run: |
curl -H "Authorization: Bearer ${{ secrets.VAULT_TOKEN }}" \
https://gitcaddy.example.com/api/vault/secrets/production-db-password
Audit Logs and Version History
Vault maintains comprehensive audit logs:
-
Navigate to Vault → Audit Logs
-
View all operations:
- Secret creation, updates, deletions
- Access token generation and usage
- User who performed each action
- Timestamp of each operation
-
Version History: Click on a secret to view all previous versions
-
Rollback: Restore a previous version if needed
Vault Licensing Tiers:
- Solo: Basic secrets management
- Pro: Advanced access controls
- Team: Multi-user collaboration features
- Enterprise: Full audit logging and compliance features
Package Registry
GitCaddy includes a multi-format package registry supporting popular ecosystems.
Publishing Packages
npm Packages
Configure npm to use GitCaddy registry:
# Set registry URL
npm config set registry https://gitcaddy.example.com/api/packages/username/npm/
# Authenticate
npm login --registry=https://gitcaddy.example.com/api/packages/username/npm/
# Publish package
npm publish
Docker Images
# Login to registry
docker login gitcaddy.example.com
# Tag image
docker tag myimage:latest gitcaddy.example.com/username/myimage:latest
# Push image
docker push gitcaddy.example.com/username/myimage:latest
Maven Packages
Add to your pom.xml:
<distributionManagement>
<repository>
<id>gitcaddy</id>
<url>https://gitcaddy.example.com/api/packages/username/maven</url>
</repository>
</distributionManagement>
Deploy with Maven:
mvn deploy
Python Packages (PyPI)
Configure .pypirc:
[distutils]
index-servers = gitcaddy
[gitcaddy]
repository = https://gitcaddy.example.com/api/packages/username/pypi
username = your-username
password = your-token
Upload package:
python setup.py sdist bdist_wheel
twine upload --repository gitcaddy dist/*
Installing Packages
GitCaddy provides installation instructions for each package in the web interface:
- Navigate to Packages in your repository or user profile
- Click on a package
- View ecosystem-specific installation commands
Example for npm:
npm install --registry=https://gitcaddy.example.com/api/packages/username/npm/ package-name
AI-Powered Features
GitCaddy integrates AI capabilities to enhance code quality and productivity.
AI Code Review
Enable AI-assisted code reviews to receive automated feedback on pull requests.
Enabling AI Code Review
- Navigate to Repository Settings → AI Features
- Enable "AI Code Review"
- Configure review preferences:
- Review depth: Quick scan or comprehensive analysis
- Focus areas: Security, performance, best practices
- Auto-comment: Automatically post suggestions as PR comments
How It Works
When a pull request is created:
-
AI analyzes the code changes
-
Identifies potential issues:
- Security vulnerabilities
- Performance bottlenecks
- Code smells and anti-patterns
- Style inconsistencies
-
Posts suggestions as PR comments
-
Provides explanations and recommended fixes
Example AI Comment:
🤖 AI Code Review
Potential Security Issue: SQL query is vulnerable to injection attacks.
Location:
src/database.js:45Recommendation: Use parameterized queries instead of string concatenation.
// Instead of: const query = `SELECT * FROM users WHERE id = ${userId}`; // Use: const query = 'SELECT * FROM users WHERE id = ?'; db.query(query, [userId]);
AI Issue Triage
AI automatically categorizes and prioritizes new issues.
Enabling AI Issue Triage
- Navigate to Repository Settings → AI Features
- Enable "AI Issue Triage"
- Configure triage rules:
- Auto-label: Automatically apply labels based on content
- Priority assignment: Suggest priority levels
- Similar issues: Link to related issues
How It Works
When an issue is created:
- AI analyzes the issue title and description
- Suggests appropriate labels (bug, enhancement, documentation, etc.)
- Identifies priority based on keywords and context
- Finds similar existing issues to prevent duplicates
Code Explanation
Get AI-generated explanations for complex code.
Using Code Explanation
- Navigate to a file in your repository
- Select a code block
- Click the "Explain with AI" button
- View the explanation in plain language
Example:
const memoize = (fn) => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
};
};
AI Explanation:
This code implements a memoization function, which is a performance optimization technique. It creates a cache to store the results of expensive function calls. When the function is called with the same arguments again, it returns the cached result instead of recalculating it. This is useful for pure functions with expensive computations.
Organizations and Teams
Organizations enable collaborative management of multiple repositories with team-based permissions.
Creating Organizations
-
Click the "+" icon in the top navigation
-
Select "New Organization"
-
Fill in organization details:
- Organization Name: Unique identifier
- Display Name: Full name
- Description: Organization purpose
- Website: Optional URL
- Location: Optional location
-
Click "Create Organization"
Managing Teams
Teams group users within an organization and control access to repositories.
Creating a Team
-
Navigate to your organization
-
Click the "Teams" tab
-
Click "New Team"
-
Configure team settings:
- Team Name: Descriptive name
- Description: Team purpose
- Visibility: Visible or hidden
-
Click "Create Team"
Adding Team Members
- Open the team
- Click "Add Member"
- Search for users and click "Add"
- Assign roles:
- Member: Standard access
- Admin: Can manage team settings
Team Permissions
Control repository access per team:
- Navigate to Teams → Select a team
- Click "Repositories"
- Click "Add Repository"
- Select repository and set permissions:
- Read: View code and issues
- Write: Push commits, create issues/PRs
- Admin: Full repository management
Best Practice: Use teams to implement the principle of least privilege. Grant only the permissions necessary for each team's responsibilities.
Landing Pages and Custom Domains
Create professional landing pages for your repositories with custom domains.
Enabling Landing Pages
-
Navigate to Repository Settings → Pages
-
Enable "Landing Pages"
-
Configure page settings:
- Source: Select branch and directory (e.g.,
main/docs) - Custom Domain: Enter your domain (e.g.,
docs.myproject.com) - SSL/TLS: Enable HTTPS with automatic certificate
- Source: Select branch and directory (e.g.,
-
Customize your landing page:
- Hero Section: Add title, subtitle, and call-to-action
- Features: Highlight key features with icons
- Pricing: Display pricing tiers
- Branding: Upload logo and customize colors
-
Click "Save Settings"
Configuring Custom Domains
-
In your DNS provider, add a CNAME record:
docs.myproject.com CNAME gitcaddy.example.com -
In GitCaddy Pages settings, enter the custom domain
-
Click "Verify Domain"
-
Enable "Enforce HTTPS" for automatic SSL certificate
Your landing page will be accessible at https://docs.myproject.com
SEO Optimization
Optimize landing pages for search engines:
- Navigate to Pages → SEO Settings
- Configure meta tags:
- Title: Page title for search results
- Description: Meta description
- Keywords: Relevant keywords
- Open Graph: Social media preview settings
Authentication and Security
GitCaddy provides multiple authentication methods and security features.
Two-Factor Authentication
Enhance account security with 2FA.
Enabling 2FA
- Navigate to Settings → Security
- Click "Enable Two-Factor Authentication"
- Scan the QR code with an authenticator app (Google Authenticator, Authy, etc.)
- Enter the verification code
- Save recovery codes in a secure location
- Click "Enable 2FA"
WebAuthn (Hardware Keys)
Use hardware security keys for passwordless authentication:
- Navigate to Settings → Security → WebAuthn
- Click "Add Security Key"
- Enter a nickname for the key
- Follow browser prompts to register your key
- Test the key by logging out and back in
SSH and GPG Keys
Adding SSH Keys
-
Generate an SSH key pair on your machine:
ssh-keygen -t ed25519 -C "your_email@example.com" -
Navigate to Settings → SSH / GPG Keys
-
Click "Add Key"
-
Paste your public key (
~/.ssh/id_ed25519.pub) -
Give it a descriptive name
-
Click "Add Key"
Test your SSH connection:
ssh -T git@gitcaddy.example.com
Signing Commits with GPG
-
Generate a GPG key:
gpg --full-generate-key -
Export your public key:
gpg --armor --export your_email@example.com -
Navigate to Settings → SSH / GPG Keys → GPG Keys
-
Click "Add Key" and paste your public key
-
Configure Git to sign commits:
git config --global user.signingkey YOUR_KEY_ID git config --global commit.gpgsign true
Signed commits display a "Verified" badge in GitCaddy.
OAuth2 and SSO
Configure external authentication providers for single sign-on.
Supported Providers
- GitHub
- GitLab
- Microsoft Azure AD
- LDAP/Active Directory
- SAML 2.0
- OpenID Connect
Configuring OAuth2 (Admin)
-
Navigate to Site Administration → Authentication Sources
-
Click "Add Authentication Source"
-
Select provider type (e.g., OAuth2)
-
Configure provider settings:
- Client ID: From provider
- Client Secret: From provider
- Authorization URL: Provider-specific
- Token URL: Provider-specific
- User Info URL: Provider-specific
-
Click "Add Authentication Source"
Users can now log in using the external provider.
Customization and Settings
User Preferences
Personalize your GitCaddy experience:
-
Navigate to Settings → Profile
-
Configure preferences:
- Display Name: Your full name
- Email: Primary email address
- Website: Personal or company website
- Location: Your location
- Biography: Brief description
-
Appearance Settings:
- Language: Select from 18+ supported languages (English, German, Hindi, Italian, Polish, Portuguese, etc.)
- Theme: Light, dark, or auto (system preference)
-
Notification Settings:
- Email Notifications: Configure which events trigger emails
- Web Notifications: Enable browser notifications
- Watching: Auto-watch repositories you create or contribute to
Repository Settings
Configure individual repository settings:
-
Navigate to your repository → Settings
-
General:
- Repository name, description, website
- Visibility (public/private)
- Template repository
- Archive repository
-
Features:
- Enable/disable issues, wiki, projects, actions
- External wiki URL
- External issue tracker
-
Collaborators:
- Add users with specific permissions
- Manage access levels
-
Branches:
- Default branch
- Branch protection rules
- Required status checks
-
Webhooks:
- Configure webhooks for external integrations
Webhooks and Integrations
Integrate GitCaddy with external services.
Creating a Webhook
-
Navigate to Repository Settings → Webhooks
-
Click "Add Webhook"
-
Configure webhook:
- Payload URL: Endpoint to receive events
- Content Type: JSON or form-encoded
- Secret: Optional secret for verification
- Events: Select which events trigger the webhook
- Push events
- Pull request events
- Issue events
- Release events
- etc.
-
Click "Add Webhook"
Supported Integrations
GitCaddy provides pre-configured integrations for:
- Slack: Post notifications to Slack channels
- Discord: Send updates to Discord servers
- Microsoft Teams: Integrate with Teams channels
- Matrix: Connect to Matrix chat rooms
- Telegram: Send notifications to Telegram
- Email: Custom email notifications
Example: Slack Integration
- Create an incoming webhook in Slack
- In GitCaddy, add a Slack webhook
- Paste the Slack webhook URL
- Select events to post (push, PR, issues)
- Customize message format and channel
Tips and Best Practices
Repository Management
- Use Templates: Create repository templates for common project structures to save time
- Branch Protection: Always enable branch protection on
mainandproductionbranches - Required Reviews: Enforce at least one code review before merging pull requests
- Status Checks: Set up CI/CD workflows as required status checks
- CODEOWNERS File: Create a
CODEOWNERSfile to automatically request reviews from relevant team members
Issue Tracking
- Labels: Establish a consistent labeling system across repositories
- Templates: Create issue templates for bug reports, feature requests, and questions
- Milestones: Use milestones to track progress toward releases
- Project Boards: Visualize work with project boards for sprint planning
- Time Tracking: Estimate and track time for better project planning
Pull Requests
- Small PRs: Keep pull requests focused and small for easier review
- Descriptive Titles: Write clear, descriptive PR titles
- Link Issues: Always reference related issues in PR descriptions
- Draft PRs: Use draft pull requests for work-in-progress code
- Review Checklist: Create a PR template with a review checklist
CI/CD Workflows
- Matrix Testing: Test across multiple versions and platforms
- Caching: Cache dependencies to speed up workflow runs
- Artifacts: Upload build artifacts and test results
- Conditional Jobs: Use conditions to skip unnecessary jobs
- Secrets Management: Use Vault for sensitive credentials
Security
- 2FA: Require two-factor authentication for all organization members
- Signed Commits: Enforce GPG-signed commits for critical repositories
- Dependency Scanning: Set up automated dependency vulnerability scanning
- Secret Scanning: Enable secret scanning to prevent credential leaks
- Regular Audits: Review access permissions and audit logs regularly
Performance
- LFS for Large Files: Use Git LFS for binary files and large assets
- Shallow Clones: Use shallow clones in CI/CD to reduce clone time
- Archive Inactive Repos: Archive repositories that are no longer maintained
- Cleanup: Regularly clean up old branches and tags
Troubleshooting
Authentication Issues
Problem: Cannot push or pull from repository
Solutions:
- Verify SSH key is added to your GitCaddy account
- Test SSH connection:
ssh -T git@gitcaddy.example.com - For HTTPS, ensure you're using a personal access token, not your password
- Check repository permissions (you may only have read access)
Problem: 2FA code not working
Solutions:
- Ensure your device clock is synchronized (2FA is time-based)
- Try using a recovery code instead
- Contact an administrator to reset 2FA if locked out
Workflow Issues
Problem: GitCaddy Actions workflow not triggering
Solutions:
- Verify the workflow file is in
.gitea/workflows/directory - Check YAML syntax (use a YAML validator)
- Ensure the trigger events match your actions (e.g.,
on: push) - Check if Actions are enabled in repository settings
- Verify at least one runner is online and available
Problem: Workflow fails with "runner not found"
Solutions:
- Check runner status in Settings → Actions → Runners
- Restart the runner service
- Verify runner labels match workflow requirements
- Check runner logs for connection issues
Repository Issues
Problem: Large repository clone is slow
Solutions:
- Use shallow clone:
git clone --depth=1 <url> - Enable Git LFS for large files
- Consider using sparse checkout for monorepos
- Check network connectivity and bandwidth
Problem: Cannot merge pull request
Solutions:
- Resolve merge conflicts locally and push
- Ensure all required status checks pass
- Verify you have required approvals
- Check branch protection rules
- Ensure you have write permissions
Vault Issues
Problem: Cannot access Vault secrets in workflow
Solutions:
- Verify access token has correct permissions
- Check token hasn't expired
- Ensure secret key name matches exactly (case-sensitive)
- Verify Vault is enabled for the repository/organization
Package Registry Issues
Problem: Cannot publish package
Solutions:
- Verify authentication credentials
- Check package name doesn't conflict with existing package
- Ensure you have write permissions to the registry
- Review package manifest for errors
- Check registry URL is correct for the package type
Problem: Cannot install package
Solutions:
- Verify registry URL is configured correctly
- Check authentication if package is private
- Ensure package version exists
- Try clearing package manager cache
Performance Issues
Problem: GitCaddy web interface is slow
Solutions:
- Check server resources (CPU, memory, disk)
- Review database performance and optimize queries
- Enable caching in
app.iniconfiguration - Check for large repositories causing indexing delays
- Review logs for errors:
./gitcaddy admin logs
Problem: Git operations are slow
Solutions:
- Run
git gcto optimize repository - Check if repository needs LFS for large files
- Verify network latency between client and server
- Consider using SSH instead of HTTPS (or vice versa)
Getting Help
If you continue to experience issues:
- Documentation: Check the official GitCaddy documentation
- Community Forum: Search or post in the community forum
- Issue Tracker: Report bugs in the GitCaddy repository
- Admin Logs: Review system logs in Site Administration → Monitoring
- Support: Contact your GitCaddy administrator or support team
Useful Commands:
# Check GitCaddy version
./gitcaddy --version
# View logs
./gitcaddy admin logs
# Run diagnostics
./gitcaddy doctor
# Database maintenance
./gitcaddy admin regenerate hooks
./gitcaddy admin regenerate keys
Conclusion
GitCaddy provides a comprehensive, self-hosted solution for Git repository management with powerful features for collaboration, automation, and security. This guide has covered the essential workflows and features to help you get started and become productive quickly.
For advanced topics, enterprise features, and administrative configuration, refer to the official GitCaddy documentation or contact your system administrator.
Happy coding! 🚀
GitCaddy API Reference
Complete technical reference for developers integrating with or using GitCaddy, a self-hosted Git repository management platform.
Table of Contents
- Introduction
- Authentication
- REST API Endpoints
- Git Protocol
- WebSocket APIs
- Frontend JavaScript APIs
- Error Codes
- Rate Limiting
- Webhooks
- Code Examples
Introduction
GitCaddy provides comprehensive REST APIs for repository management, collaboration tools, CI/CD workflows, package registry, and enterprise features. All API endpoints are accessible at:
https://your-gitcaddy-instance.com/api/v1/
Base URL Format:
https://{instance}/api/v1/{endpoint}
Content Type:
All requests and responses use application/json unless otherwise specified.
API Versioning:
Current stable version: v1
Authentication
GitCaddy supports multiple authentication methods for API access.
Personal Access Tokens
Personal access tokens (PATs) provide programmatic access to the GitCaddy API.
Creating a Token:
- Navigate to User Settings → Applications → Manage Access Tokens
- Click "Generate New Token"
- Set token name and scopes
- Copy the generated token (shown only once)
Using Tokens:
Include the token in the Authorization header:
Authorization: token YOUR_ACCESS_TOKEN
Example Request:
curl -H "Authorization: token abc123def456" \
https://gitcaddy.example.com/api/v1/user
Token Scopes:
| Scope | Description |
|---|---|
repo |
Full access to repositories |
repo:status |
Read-only access to repository status |
public_repo |
Access to public repositories only |
admin:org |
Full organization administration |
write:org |
Write access to organizations |
read:org |
Read-only organization access |
admin:public_key |
Manage public SSH keys |
admin:repo_hook |
Manage repository webhooks |
admin:org_hook |
Manage organization webhooks |
notification |
Access notifications |
user |
Full user profile access |
read:user |
Read-only user profile access |
user:email |
Access user email addresses |
delete_repo |
Delete repositories |
package |
Access package registry |
admin:gpg_key |
Manage GPG keys |
admin:application |
Manage OAuth applications |
OAuth2 Authentication
GitCaddy supports OAuth2 for third-party application integration.
OAuth2 Flow:
-
Register Application:
- User Settings → Applications → OAuth2 Applications
- Create new OAuth2 application
- Note
client_idandclient_secret
-
Authorization Request:
GET /login/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code&state={state}
- Token Exchange:
POST /login/oauth/access_token
Content-Type: application/json
{
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"code": "authorization_code",
"grant_type": "authorization_code",
"redirect_uri": "https://your-app.com/callback"
}
Response:
{
"access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a",
"token_type": "bearer",
"scope": "repo,user"
}
- Using Access Token:
Authorization: Bearer gho_16C7e42F292c6912E7710c838347Ae178B4a
Supported OAuth2 Providers:
GitCaddy can authenticate users via external OAuth2 providers:
- GitHub
- GitLab
- Bitbucket
- Microsoft Azure AD
- Custom OpenID Connect providers
WebAuthn (Passkeys)
GitCaddy supports WebAuthn for passwordless authentication and two-factor authentication.
Registration API:
// Client-side registration
const response = await fetch('/user/settings/security/webauthn/register', {
method: 'GET',
credentials: 'include'
});
const options = await response.json();
// Create credential
const credential = await navigator.credentials.create({
publicKey: options
});
// Send credential to server
await fetch('/user/settings/security/webauthn/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'My Security Key',
credential: credential
})
});
Authentication API:
// Get authentication challenge
const response = await fetch('/user/webauthn/assertion', {
method: 'GET'
});
const options = await response.json();
// Get credential
const assertion = await navigator.credentials.get({
publicKey: options
});
// Verify assertion
await fetch('/user/webauthn/assertion', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(assertion)
});
REST API Endpoints
Repository APIs
List User Repositories
GET /api/v1/user/repos
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
page |
integer | No | Page number (default: 1) |
limit |
integer | No | Page size (default: 10, max: 50) |
type |
string | No | Filter by type: owner, collaborator, member |
Response:
[
{
"id": 1,
"owner": {
"id": 1,
"login": "username",
"full_name": "User Name",
"avatar_url": "https://gitcaddy.example.com/avatars/1"
},
"name": "my-repo",
"full_name": "username/my-repo",
"description": "Repository description",
"private": false,
"fork": false,
"parent": null,
"empty": false,
"mirror": false,
"size": 1024,
"html_url": "https://gitcaddy.example.com/username/my-repo",
"ssh_url": "git@gitcaddy.example.com:username/my-repo.git",
"clone_url": "https://gitcaddy.example.com/username/my-repo.git",
"website": "",
"stars_count": 5,
"forks_count": 2,
"watchers_count": 3,
"open_issues_count": 1,
"default_branch": "main",
"archived": false,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-15T12:30:00Z",
"permissions": {
"admin": true,
"push": true,
"pull": true
}
}
]
Create Repository
POST /api/v1/user/repos
Request Body:
{
"name": "new-repo",
"description": "My new repository",
"private": false,
"auto_init": true,
"gitignores": "Go",
"license": "MIT",
"readme": "Default",
"default_branch": "main"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Repository name |
description |
string | No | Repository description |
private |
boolean | No | Create as private (default: false) |
auto_init |
boolean | No | Initialize with README (default: false) |
gitignores |
string | No | .gitignore template name |
license |
string | No | License template (MIT, Apache-2.0, GPL-3.0, etc.) |
readme |
string | No | README template |
default_branch |
string | No | Default branch name (default: main) |
trust_model |
string | No | Trust model: default, collaborator, committer, collaboratorcommitter |
Response: 201 Created
{
"id": 2,
"name": "new-repo",
"full_name": "username/new-repo",
"private": false,
"html_url": "https://gitcaddy.example.com/username/new-repo",
"clone_url": "https://gitcaddy.example.com/username/new-repo.git",
"created_at": "2024-01-20T10:00:00Z"
}
Get Repository
GET /api/v1/repos/{owner}/{repo}
Response:
{
"id": 1,
"owner": {
"id": 1,
"login": "username",
"full_name": "User Name"
},
"name": "my-repo",
"full_name": "username/my-repo",
"description": "Repository description",
"private": false,
"default_branch": "main",
"permissions": {
"admin": true,
"push": true,
"pull": true
}
}
Delete Repository
DELETE /api/v1/repos/{owner}/{repo}
Response: 204 No Content
List Repository Branches
GET /api/v1/repos/{owner}/{repo}/branches
Response:
[
{
"name": "main",
"commit": {
"id": "abc123def456",
"message": "Initial commit",
"url": "https://gitcaddy.example.com/username/my-repo/commit/abc123def456"
},
"protected": true,
"user_can_push": true,
"user_can_merge": true
}
]
Create Branch
POST /api/v1/repos/{owner}/{repo}/branches
Request Body:
{
"new_branch_name": "feature-branch",
"old_branch_name": "main"
}
Get Branch Protection
GET /api/v1/repos/{owner}/{repo}/branch_protections/{branch}
Response:
{
"branch_name": "main",
"enable_push": false,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["admin"],
"push_whitelist_teams": ["core-team"],
"push_whitelist_deploy_keys": false,
"enable_merge_whitelist": true,
"merge_whitelist_usernames": ["maintainer"],
"merge_whitelist_teams": ["reviewers"],
"enable_status_check": true,
"status_check_contexts": ["ci/tests", "ci/lint"],
"required_approvals": 2,
"enable_approvals_whitelist": false,
"block_on_rejected_reviews": true,
"dismiss_stale_approvals": true,
"require_signed_commits": true,
"protected_file_patterns": "*.lock",
"unprotected_file_patterns": "docs/*"
}
List Repository Tags
GET /api/v1/repos/{owner}/{repo}/tags
Response:
[
{
"name": "v1.0.0",
"commit": {
"sha": "abc123def456",
"url": "https://gitcaddy.example.com/username/my-repo/commit/abc123def456"
},
"zipball_url": "https://gitcaddy.example.com/username/my-repo/archive/v1.0.0.zip",
"tarball_url": "https://gitcaddy.example.com/username/my-repo/archive/v1.0.0.tar.gz"
}
]
Get File Contents
GET /api/v1/repos/{owner}/{repo}/contents/{filepath}?ref={branch}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ref |
string | No | Branch, tag, or commit SHA (default: default branch) |
Response:
{
"name": "README.md",
"path": "README.md",
"sha": "abc123",
"type": "file",
"size": 1024,
"encoding": "base64",
"content": "IyBNeVJlcG8KClRoaXMgaXMgYSBSRUFETUUgZmlsZS4=",
"target": null,
"url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/contents/README.md",
"html_url": "https://gitcaddy.example.com/username/my-repo/src/branch/main/README.md",
"git_url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/git/blobs/abc123",
"download_url": "https://gitcaddy.example.com/username/my-repo/raw/branch/main/README.md"
}
Create/Update File
POST /api/v1/repos/{owner}/{repo}/contents/{filepath}
Request Body:
{
"content": "base64_encoded_content",
"message": "Create README.md",
"branch": "main",
"sha": "abc123def456",
"author": {
"name": "Author Name",
"email": "author@example.com"
},
"committer": {
"name": "Committer Name",
"email": "committer@example.com"
},
"dates": {
"author": "2024-01-20T10:00:00Z",
"committer": "2024-01-20T10:00:00Z"
},
"signoff": false,
"new_branch": "feature-branch"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
content |
string | Yes | Base64-encoded file content |
message |
string | Yes | Commit message |
branch |
string | No | Branch name (default: default branch) |
sha |
string | No | Blob SHA for update (required when updating) |
new_branch |
string | No | Create new branch for commit |
Delete File
DELETE /api/v1/repos/{owner}/{repo}/contents/{filepath}
Request Body:
{
"message": "Delete file",
"sha": "abc123def456",
"branch": "main"
}
Fork Repository
POST /api/v1/repos/{owner}/{repo}/forks
Request Body:
{
"organization": "my-org",
"name": "forked-repo"
}
List Forks
GET /api/v1/repos/{owner}/{repo}/forks
Mirror Repository
POST /api/v1/repos/migrate
Request Body:
{
"clone_addr": "https://github.com/user/repo.git",
"auth_username": "username",
"auth_password": "password_or_token",
"uid": 1,
"repo_name": "mirrored-repo",
"mirror": true,
"private": false,
"description": "Mirrored repository"
}
Issue APIs
List Repository Issues
GET /api/v1/repos/{owner}/{repo}/issues
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
state |
string | No | Filter by state: open, closed, all (default: open) |
labels |
string | No | Comma-separated label IDs or names |
q |
string | No | Search query |
type |
string | No | Filter by type: issues, pulls |
milestones |
string | No | Comma-separated milestone names |
since |
string | No | Only issues updated after this time (ISO 8601) |
before |
string | No | Only issues updated before this time (ISO 8601) |
created_by |
string | No | Filter by creator username |
assigned_by |
string | No | Filter by assignee username |
mentioned_by |
string | No | Filter by mentioned username |
page |
integer | No | Page number |
limit |
integer | No | Page size |
Response:
[
{
"id": 1,
"url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/issues/1",
"html_url": "https://gitcaddy.example.com/username/my-repo/issues/1",
"number": 1,
"user": {
"id": 1,
"login": "username",
"full_name": "User Name"
},
"title": "Bug: Application crashes on startup",
"body": "Detailed description of the issue...",
"labels": [
{
"id": 1,
"name": "bug",
"color": "#ee0701",
"description": "Something isn't working"
}
],
"milestone": {
"id": 1,
"title": "v1.0",
"description": "First release",
"state": "open",
"due_on": "2024-12-31T23:59:59Z"
},
"assignees": [
{
"id": 2,
"login": "developer"
}
],
"state": "open",
"is_locked": false,
"comments": 3,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-16T14:30:00Z",
"closed_at": null,
"due_date": null,
"pull_request": null
}
]
Create Issue
POST /api/v1/repos/{owner}/{repo}/issues
Request Body:
{
"title": "New issue title",
"body": "Issue description with **markdown** support",
"assignees": ["developer1", "developer2"],
"labels": [1, 2],
"milestone": 1,
"closed": false,
"due_date": "2024-12-31T23:59:59Z",
"ref": "main"
}
Response: 201 Created
Get Issue
GET /api/v1/repos/{owner}/{repo}/issues/{index}
Update Issue
PATCH /api/v1/repos/{owner}/{repo}/issues/{index}
Request Body:
{
"title": "Updated title",
"body": "Updated description",
"state": "closed",
"assignees": ["user1"],
"labels": [1, 3],
"milestone": 2,
"due_date": "2024-12-31T23:59:59Z",
"unset_due_date": false
}
List Issue Comments
GET /api/v1/repos/{owner}/{repo}/issues/{index}/comments
Response:
[
{
"id": 1,
"html_url": "https://gitcaddy.example.com/username/my-repo/issues/1#issuecomment-1",
"pull_request_url": "",
"issue_url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/issues/1",
"user": {
"id": 1,
"login": "username"
},
"original_author": "",
"original_author_id": 0,
"body": "This is a comment on the issue",
"created_at": "2024-01-15T11:00:00Z",
"updated_at": "2024-01-15T11:00:00Z"
}
]
Create Issue Comment
POST /api/v1/repos/{owner}/{repo}/issues/{index}/comments
Request Body:
{
"body": "Comment text with **markdown** support"
}
Edit Issue Comment
PATCH /api/v1/repos/{owner}/{repo}/issues/comments/{id}
Delete Issue Comment
DELETE /api/v1/repos/{owner}/{repo}/issues/comments/{id}
List Issue Labels
GET /api/v1/repos/{owner}/{repo}/labels
Response:
[
{
"id": 1,
"name": "bug",
"color": "#ee0701",
"description": "Something isn't working",
"url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/labels/1"
}
]
Create Label
POST /api/v1/repos/{owner}/{repo}/labels
Request Body:
{
"name": "enhancement",
"color": "#a2eeef",
"description": "New feature or request"
}
Track Time on Issue
POST /api/v1/repos/{owner}/{repo}/issues/{index}/times
Request Body:
{
"time": 3600,
"created": "2024-01-15T10:00:00Z",
"user_name": "username"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
time |
integer | Yes | Time in seconds |
created |
string | No | Timestamp (ISO 8601) |
user_name |
string | No | Username (admin only) |
List Tracked Times
GET /api/v1/repos/{owner}/{repo}/issues/{index}/times
Pull Request APIs
List Pull Requests
GET /api/v1/repos/{owner}/{repo}/pulls
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
state |
string | No | Filter by state: open, closed, all |
sort |
string | No | Sort by: oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority |
milestone |
integer | No | Filter by milestone ID |
labels |
string | No | Comma-separated label IDs |
page |
integer | No | Page number |
limit |
integer | No | Page size |
Response:
[
{
"id": 1,
"url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/pulls/1",
"number": 1,
"user": {
"id": 1,
"login": "contributor"
},
"title": "Add new feature",
"body": "This PR adds a new feature...",
"labels": [],
"milestone": null,
"assignees": [],
"state": "open",
"is_locked": false,
"comments": 2,
"html_url": "https://gitcaddy.example.com/username/my-repo/pulls/1",
"diff_url": "https://gitcaddy.example.com/username/my-repo/pulls/1.diff",
"patch_url": "https://gitcaddy.example.com/username/my-repo/pulls/1.patch",
"mergeable": true,
"merged": false,
"merged_at": null,
"merge_commit_sha": null,
"merged_by": null,
"base": {
"label": "main",
"ref": "main",
"sha": "abc123",
"repo_id": 1,
"repo": {
"id": 1,
"name": "my-repo",
"full_name": "username/my-repo"
}
},
"head": {
"label": "contributor:feature-branch",
"ref": "feature-branch",
"sha": "def456",
"repo_id": 2,
"repo": {
"id": 2,
"name": "my-repo",
"full_name": "contributor/my-repo"
}
},
"merge_base": "abc123",
"due_date": null,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-16T14:30:00Z",
"closed_at": null
}
]
Create Pull Request
POST /api/v1/repos/{owner}/{repo}/pulls
Request Body:
{
"title": "Add new feature",
"body": "Detailed description of changes",
"head": "feature-branch",
"base": "main",
"assignees": ["reviewer1"],
"labels": [1],
"milestone": 1,
"due_date": "2024-12-31T23:59:59Z"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | PR title |
body |
string | No | PR description |
head |
string | Yes | Branch containing changes |
base |
string | Yes | Branch to merge into |
assignees |
array | No | Array of usernames |
labels |
array | No | Array of label IDs |
milestone |
integer | No | Milestone ID |
Get Pull Request
GET /api/v1/repos/{owner}/{repo}/pulls/{index}
Update Pull Request
PATCH /api/v1/repos/{owner}/{repo}/pulls/{index}
Request Body:
{
"title": "Updated title",
"body": "Updated description",
"base": "main",
"assignees": ["reviewer1", "reviewer2"],
"labels": [1, 2],
"milestone": 1,
"state": "closed",
"due_date": "2024-12-31T23:59:59Z"
}
Merge Pull Request
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/merge
Request Body:
{
"Do": "merge",
"MergeMessageField": "Merge pull request #1",
"MergeTitleField": "Add new feature",
"delete_branch_after_merge": true,
"force_merge": false,
"head_commit_id": "def456",
"merge_when_checks_succeed": false
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
Do |
string | Yes | Merge method: merge, rebase, rebase-merge, squash, manually-merged |
MergeMessageField |
string | No | Merge commit message |
MergeTitleField |
string | No | Merge commit title |
delete_branch_after_merge |
boolean | No | Delete head branch after merge |
force_merge |
boolean | No | Force merge even if checks fail |
head_commit_id |
string | No | Expected head commit SHA |
List PR Reviews
GET /api/v1/repos/{owner}/{repo}/pulls/{index}/reviews
Response:
[
{
"id": 1,
"user": {
"id": 2,
"login": "reviewer"
},
"body": "Looks good to me!",
"commit_id": "def456",
"state": "APPROVED",
"html_url": "https://gitcaddy.example.com/username/my-repo/pulls/1#pullrequestreview-1",
"submitted_at": "2024-01-16T10:00:00Z"
}
]
Create PR Review
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/reviews
Request Body:
{
"body": "Review comment",
"event": "APPROVED",
"comments": [
{
"path": "src/main.go",
"body": "Consider refactoring this function",
"old_position": 0,
"new_position": 42
}
]
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
body |
string | No | Overall review comment |
event |
string | Yes | Review state: APPROVED, REQUEST_CHANGES, COMMENT |
comments |
array | No | Array of line comments |
Submit PR Review
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/reviews/{id}
Dismiss PR Review
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals
Request Body:
{
"message": "Outdated review"
}
Request AI Code Review
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/ai-review
Request Body:
{
"provider": "openai",
"model": "gpt-4"
}
Response:
{
"review_id": 42,
"status": "pending",
"message": "AI review requested. Results will be posted as comments."
}
Organization APIs
List Organizations
GET /api/v1/orgs
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
page |
integer | No | Page number |
limit |
integer | No | Page size |
Get Organization
GET /api/v1/orgs/{org}
Response:
{
"id": 1,
"username": "my-org",
"full_name": "My Organization",
"avatar_url": "https://gitcaddy.example.com/avatars/1",
"description": "Organization description",
"website": "https://example.com",
"location": "San Francisco, CA",
"visibility": "public",
"repo_admin_change_team_access": false,
"username": "my-org"
}
Create Organization
POST /api/v1/orgs
Request Body:
{
"username": "new-org",
"full_name": "New Organization",
"description": "Organization description",
"website": "https://example.com",
"location": "San Francisco, CA",
"visibility": "public",
"repo_admin_change_team_access": false
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
username |
string | Yes | Organization username |
full_name |
string | No | Display name |
description |
string | No | Organization description |
website |
string | No | Website URL |
location |
string | No | Location |
visibility |
string | No | Visibility: public, limited, private |
Edit Organization
PATCH /api/v1/orgs/{org}
Delete Organization
DELETE /api/v1/orgs/{org}
List Organization Teams
GET /api/v1/orgs/{org}/teams
Response:
[
{
"id": 1,
"name": "core-team",
"description": "Core development team",
"organization": {
"id": 1,
"username": "my-org",
"full_name": "My Organization"
},
"permission": "admin",
"can_create_org_repo": true,
"includes_all_repositories": false,
"units": [
"repo.code",
"repo.issues",
"repo.pulls",
"repo.releases",
"repo.wiki"
]
}
]
Create Team
POST /api/v1/orgs/{org}/teams
Request Body:
{
"name": "new-team",
"description": "Team description",
"permission": "write",
"can_create_org_repo": false,
"includes_all_repositories": false,
"units": [
"repo.code",
"repo.issues",
"repo.pulls"
]
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Team name |
description |
string | No | Team description |
permission |
string | No | Permission level: read, write, admin |
units |
array | No | Repository unit permissions |
List Team Members
GET /api/v1/teams/{id}/members
Add Team Member
PUT /api/v1/teams/{id}/members/{username}
Remove Team Member
DELETE /api/v1/teams/{id}/members/{username}
List Team Repositories
GET /api/v1/teams/{id}/repos
Add Team Repository
PUT /api/v1/teams/{id}/repos/{org}/{repo}
User APIs
Get Authenticated User
GET /api/v1/user
Response:
{
"id": 1,
"login": "username",
"full_name": "User Name",
"email": "user@example.com",
"avatar_url": "https://gitcaddy.example.com/avatars/1",
"language": "en-US",
"is_admin": false,
"last_login": "2024-01-20T10:00:00Z",
"created": "2023-01-01T00:00:00Z",
"restricted": false,
"active": true,
"prohibit_login": false,
"location": "San Francisco",
"website": "https://example.com",
"description": "User bio",
"visibility": "public",
"followers_count": 10,
"following_count": 5,
"starred_repos_count": 20
}
Get User
GET /api/v1/users/{username}
List User Emails
GET /api/v1/user/emails
Response:
[
{
"email": "user@example.com",
"verified": true,
"primary": true
},
{
"email": "alternate@example.com",
"verified": false,
"primary": false
}
]
Add Email
POST /api/v1/user/emails
Request Body:
{
"emails": ["new@example.com"]
}
Delete Email
DELETE /api/v1/user/emails
Request Body:
{
"emails": ["old@example.com"]
}
List SSH Keys
GET /api/v1/user/keys
Response:
[
{
"id": 1,
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...",
"url": "https://gitcaddy.example.com/api/v1/user/keys/1",
"title": "Work Laptop",
"fingerprint": "SHA256:abc123def456",
"created_at": "2024-01-01T00:00:00Z",
"read_only": false
}
]
Add SSH Key
POST /api/v1/user/keys
Request Body:
{
"title": "My Key",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...",
"read_only": false
}
Delete SSH Key
DELETE /api/v1/user/keys/{id}
List GPG Keys
GET /api/v1/user/gpg_keys
Response:
[
{
"id": 1,
"primary_key_id": "",
"key_id": "ABC123DEF456",
"public_key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n...",
"emails": [
{
"email": "user@example.com",
"verified": true
}
],
"subkeys": [],
"can_sign": true,
"can_encrypt_comms": true,
"can_encrypt_storage": true,
"can_certify": true,
"created_at": "2024-01-01T00:00:00Z",
"expires_at": "2025-01-01T00:00:00Z"
}
]
Add GPG Key
POST /api/v1/user/gpg_keys
Request Body:
{
"armored_public_key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n..."
}
List Starred Repositories
GET /api/v1/user/starred
Star Repository
PUT /api/v1/user/starred/{owner}/{repo}
Unstar Repository
DELETE /api/v1/user/starred/{owner}/{repo}
List Watched Repositories
GET /api/v1/user/subscriptions
Watch Repository
PUT /api/v1/repos/{owner}/{repo}/subscription
Unwatch Repository
DELETE /api/v1/repos/{owner}/{repo}/subscription
Package Registry APIs
GitCaddy supports multiple package formats with dedicated API endpoints.
List Packages
GET /api/v1/packages/{owner}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
type |
string | No | Package type: npm, maven, docker, pypi, alpine, etc. |
q |
string | No | Search query |
page |
integer | No | Page number |
limit |
integer | No | Page size |
Response:
[
{
"id": 1,
"name": "my-package",
"version": "1.0.0",
"type": "npm",
"owner": {
"id": 1,
"login": "username"
},
"repository": {
"id": 1,
"name": "my-repo",
"full_name": "username/my-repo"
},
"creator": {
"id": 1,
"login": "username"
},
"html_url": "https://gitcaddy.example.com/username/-/packages/npm/my-package/1.0.0",
"created_at": "2024-01-15T10:00:00Z"
}
]
Get Package
GET /api/v1/packages/{owner}/{type}/{name}/{version}
Delete Package
DELETE /api/v1/packages/{owner}/{type}/{name}/{version}
NPM Package API
Configure npm registry:
npm config set registry https://gitcaddy.example.com/api/packages/{owner}/npm/
npm config set //gitcaddy.example.com/api/packages/{owner}/npm/:_authToken {token}
Publish package:
npm publish
Install package:
npm install @{owner}/{package}
Docker Registry API
Login:
docker login gitcaddy.example.com
Tag and push:
docker tag myimage gitcaddy.example.com/{owner}/{image}:{tag}
docker push gitcaddy.example.com/{owner}/{image}:{tag}
Pull:
docker pull gitcaddy.example.com/{owner}/{image}:{tag}
Maven Package API
Configure in pom.xml:
<repositories>
<repository>
<id>gitcaddy</id>
<url>https://gitcaddy.example.com/api/packages/{owner}/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitcaddy</id>
<url>https://gitcaddy.example.com/api/packages/{owner}/maven</url>
</repository>
</distributionManagement>
Configure authentication in ~/.m2/settings.xml:
<servers>
<server>
<id>gitcaddy</id>
<username>{username}</username>
<password>{token}</password>
</server>
</servers>
PyPI Package API
Configure pip:
pip config set global.index-url https://gitcaddy.example.com/api/packages/{owner}/pypi/simple
Upload with twine:
twine upload --repository-url https://gitcaddy.example.com/api/packages/{owner}/pypi dist/*
Actions APIs
List Workflow Runs
GET /api/v1/repos/{owner}/{repo}/actions/runs
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
status |
string | No | Filter by status: success, failure, waiting, running |
event |
string | No | Filter by event: push, pull_request, schedule |
actor |
string | No | Filter by actor username |
branch |
string | No | Filter by branch |
page |
integer | No | Page number |
limit |
integer | No | Page size |
Response:
{
"total_count": 10,
"workflow_runs": [
{
"id": 1,
"name": "CI",
"head_branch": "main",
"head_sha": "abc123def456",
"run_number": 42,
"event": "push",
"status": "completed",
"conclusion": "success",
"workflow_id": 1,
"url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/actions/runs/1",
"html_url": "https://gitcaddy.example.com/username/my-repo/actions/runs/1",
"created_at": "2024-01-20T10:00:00Z",
"updated_at": "2024-01-20T10:05:00Z",
"run_started_at": "2024-01-20T10:00:30Z"
}
]
}
Get Workflow Run
GET /api/v1/repos/{owner}/{repo}/actions/runs/{run_id}
Cancel Workflow Run
POST /api/v1/repos/{owner}/{repo}/actions/runs/{run_id}/cancel
Rerun Workflow
POST /api/v1/repos/{owner}/{repo}/actions/runs/{run_id}/rerun
List Workflow Jobs
GET /api/v1/repos/{owner}/{repo}/actions/runs/{run_id}/jobs
Response:
{
"total_count": 3,
"jobs": [
{
"id": 1,
"run_id": 1,
"name": "build",
"status": "completed",
"conclusion": "success",
"started_at": "2024-01-20T10:00:30Z",
"completed_at": "2024-01-20T10:03:00Z",
"url": "https://gitcaddy.example.com/api/v1/repos/username/my-repo/actions/jobs/1",
"html_url": "https://gitcaddy.example.com/username/my-repo/actions/runs/1/jobs/1"
}
]
}
Get Job Logs
GET /api/v1/repos/{owner}/{repo}/actions/jobs/{job_id}/logs
Response: Plain text log output
List Repository Secrets
GET /api/v1/repos/{owner}/{repo}/actions/secrets
Response:
{
"total_count": 2,
"secrets": [
{
"name": "API_KEY",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T10:00:00Z"
}
]
}
Create/Update Secret
PUT /api/v1/repos/{owner}/{repo}/actions/secrets/{secret_name}
Request Body:
{
"value": "secret_value"
}
Delete Secret
DELETE /api/v1/repos/{owner}/{repo}/actions/secrets/{secret_name}
List Runners
GET /api/v1/repos/{owner}/{repo}/actions/runners
Response:
{
"total_count": 1,
"runners": [
{
"id": 1,
"name": "runner-1",
"os": "linux",
"status": "online",
"busy": false,
"labels": [
{
"id": 1,
"name": "ubuntu-latest",
"type": "read-only"
}
]
}
]
}
Register Runner
POST /api/v1/repos/{owner}/{repo}/actions/runners/registration-token
Response:
{
"token": "RUNNER_REGISTRATION_TOKEN",
"expires_at": "2024-01-20T11:00:00Z"
}
Vault APIs
Enterprise-grade secrets management with encryption and audit logging.
List Vault Secrets
GET /api/v1/repos/{owner}/{repo}/vault/secrets
Response:
{
"total_count": 5,
"secrets": [
{
"id": "secret-id-123",
"name": "database_password",
"description": "Production database password",
"version": 3,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-15T10:00:00Z",
"created_by": {
"id": 1,
"login": "admin"
},
"last_accessed_at": "2024-01-20T09:30:00Z",
"access_count": 42
}
]
}
Create Vault Secret
POST /api/v1/repos/{owner}/{repo}/vault/secrets
Request Body:
{
"name": "api_key",
"description": "External API key",
"value": "secret_value_encrypted",
"metadata": {
"environment": "production",
"service": "payment-gateway"
}
}
Response: 201 Created
{
"id": "secret-id-456",
"name": "api_key",
"version": 1,
"created_at": "2024-01-20T10:00:00Z"
}
Get Vault Secret
GET /api/v1/repos/{owner}/{repo}/vault/secrets/{secret_id}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
version |
integer | No | Specific version (default: latest) |
Response:
{
"id": "secret-id-456",
"name": "api_key",
"description": "External API key",
"value": "decrypted_secret_value",
"version": 1,
"created_at": "2024-01-20T10:00:00Z",
"metadata": {
"environment": "production",
"service": "payment-gateway"
}
}
Update Vault Secret
PUT /api/v1/repos/{owner}/{repo}/vault/secrets/{secret_id}
Request Body:
{
"value": "new_secret_value",
"description": "Updated description"
}
Response:
{
"id": "secret-id-456",
"version": 2,
"updated_at": "2024-01-20T11:00:00Z"
}
Delete Vault Secret
DELETE /api/v1/repos/{owner}/{repo}/vault/secrets/{secret_id}
Response: 204 No Content
List Secret Versions
GET /api/v1/repos/{owner}/{repo}/vault/secrets/{secret_id}/versions
Response:
{
"total_count": 3,
"versions": [
{
"version": 3,
"created_at": "2024-01-20T10:00:00Z",
"created_by": {
"id": 1,
"login": "admin"
}
},
{
"version": 2,
"created_at": "2024-01-15T10:00:00Z",
"created_by": {
"id": 1,
"login": "admin"
}
}
]
}
Get Vault Audit Log
GET /api/v1/repos/{owner}/{repo}/vault/audit
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
secret_id |
string | No | Filter by secret ID |
action |
string | No | Filter by action: create, read, update, delete |
user |
string | No | Filter by username |
since |
string | No | Start date (ISO 8601) |
before |
string | No | End date (ISO 8601) |
page |
integer | No | Page number |
limit |
integer | No | Page size |
Response:
{
"total_count": 100,
"entries": [
{
"id": "audit-log-123",
"secret_id": "secret-id-456",
"secret_name": "api_key",
"action": "read",
"user": {
"id": 2,
"login": "developer"
},
"ip_address": "192.168.1.100",
"user_agent": "GitCaddy-Actions/1.0",
"timestamp": "2024-01-20T10:30:00Z",
"success": true
}
]
}
Generate CI/CD Token
POST /api/v1/repos/{owner}/{repo}/vault/tokens
Request Body:
{
"name": "ci-token",
"secret_ids": ["secret-id-456", "secret-id-789"],
"expires_at": "2024-12-31T23:59:59Z",
"read_only": true
}
Response:
{
"token": "vault_token_abc123def456",
"expires_at": "2024-12-31T23:59:59Z"
}
Git Protocol
GitCaddy supports standard Git protocols for repository operations.
HTTP(S) Protocol
Clone:
git clone https://gitcaddy.example.com/username/repo.git
Authentication:
Use personal access token as password:
git clone https://username:token@gitcaddy.example.com/username/repo.git
Or configure credential helper:
git config --global credential.helper store
git clone https://gitcaddy.example.com/username/repo.git
# Enter username and token when prompted
SSH Protocol
Clone:
git clone git@gitcaddy.example.com:username/repo.git
Setup:
- Generate SSH key:
ssh-keygen -t ed25519 -C "your_email@example.com"
-
Add public key to GitCaddy:
- User Settings → SSH/GPG Keys → Add Key
- Paste contents of
~/.ssh/id_ed25519.pub
-
Configure SSH:
# ~/.ssh/config
Host gitcaddy.example.com
User git
IdentityFile ~/.ssh/id_ed25519
Git LFS
Enable LFS for repository:
git lfs install
git lfs track "*.psd"
git add .gitattributes
git commit -m "Enable LFS for PSD files"
Configuration:
GitCaddy automatically handles LFS objects when pushing/pulling.
LFS API Endpoints:
POST /api/v1/repos/{owner}/{repo}/lfs/objects/batch
Request Body:
{
"operation": "upload",
"transfers": ["basic"],
"objects": [
{
"oid": "abc123def456...",
"size": 1048576
}
]
}
WebSocket APIs
GitCaddy uses WebSocket connections for real-time features.
EventSource (Server-Sent Events)
Time Tracking Updates:
const eventSource = new EventSource('/user/events');
eventSource.addEventListener('timetrack', (event) => {
const data = JSON.parse(event.data);
console.log('Time tracking update:', data);
// Update stopwatch UI
});
eventSource.addEventListener('error', (error) => {
console.error('EventSource error:', error);
});
Notification Updates:
const notificationSource = new EventSource('/api/v1/notifications/events');
notificationSource.addEventListener('notification', (event) => {
const notification = JSON.parse(event.data);
console.log('New notification:', notification);
// Display notification toast
});
SharedWorker
Shared stopwatch across tabs:
// Initialize shared worker for time tracking
const worker = new SharedWorker('/assets/js/stopwatch-worker.js');
worker.port.start();
worker.port.postMessage({
action: 'start',
issueId: 123
});
worker.port.onmessage = (event) => {
const { action, elapsed } = event.data;
if (action === 'tick') {
updateStopwatchDisplay(elapsed);
}
};
Frontend JavaScript APIs
GitCaddy provides modular JavaScript APIs for frontend functionality.
Core Utilities
DOM Manipulation
import {$, $$} from './modules/utils/dom.js';
// Select single element
const button = $('#submit-button');
// Select multiple elements
const listItems = $$('.list-item');
// Event delegation
$(document).on('click', '.dynamic-button', (event) => {
console.log('Button clicked:', event.target);
});
HTML Escaping
import {htmlEscape} from './modules/utils/html.js';
const userInput = '<script>alert("xss")</script>';
const safe = htmlEscape(userInput);
// Result: <script>alert("xss")</script>
Date/Time Utilities
import {parseISODateTime, formatDatetime} from './modules/utils/time.js';
const date = parseISODateTime('2024-01-20T10:00:00Z');
const formatted = formatDatetime(date, 'short'); // "Jan 20, 2024"
Color Utilities
import {useLightTextOnBackground} from './modules/utils/color.js';
const bgColor = '#ff0000';
const useLight = useLightTextOnBackground(bgColor);
// Returns true if light text should be used on this background
Glob Pattern Matching
import {matchGlobPattern} from './modules/utils/glob.js';
const pattern = '*.js';
const filename = 'script.js';
const matches = matchGlobPattern(pattern, filename); // true
DOM Manipulation
Creating Elements
import {createElementFromHTML} from './modules/utils/dom.js';
const html = '<div class="alert">Message</div>';
const element = createElementFromHTML(html);
document.body.appendChild(element);
Toggle Classes
import {toggleClass} from './modules/utils/dom.js';
const element = $('#my-element');
toggleClass(element, 'active', true); // Add class
toggleClass(element, 'hidden', false); // Remove class
Web Components
Absolute Date Component
<absolute-date date="2024-01-20T10:00:00Z" format="short"></absolute-date>
JavaScript API:
const dateElement = document.querySelector('absolute-date');
dateElement.setAttribute('date', '2024-01-21T12:00:00Z');
Origin URL Component
<origin-url data-url="https://example.com/page"></origin-url>
Displays sanitized origin URL with proper formatting.
Overflow Menu Component
<overflow-menu>
<button class="item">Action 1</button>
<button class="item">Action 2</button>
<button class="item">Action 3</button>
</overflow-menu>
Automatically creates overflow menu for items that don't fit.
Vue Components
File Tree Component
import {createApp} from 'vue';
import FileTreeView from './modules/features/repo-file-tree.js';
const app = createApp({
components: {
FileTreeView
},
data() {
return {
files: [
{name: 'src', type: 'dir', children: [...]},
{name: 'README.md', type: 'file'}
]
};
}
});
app.mount('#file-tree');
Template:
<file-tree-view :files="files" @file-click="handleFileClick"></file-tree-view>
Context Popup Component
import {createContextPopup} from './modules/features/context-popup.js';
const popup = createContextPopup({
items: [
{label: 'Edit', action: () => console.log('Edit')},
{label: 'Delete', action: () => console.log('Delete')}
],
position: {x: event.clientX, y: event.clientY}
});
popup.show();
Tooltip System
import {createTippy} from './modules/features/tippy.js';
// Simple tooltip
createTippy('#my-element', {
content: 'Tooltip text'
});
// HTML content
createTippy('.help-icon', {
content: '<strong>Help:</strong> This is help text',
allowHTML: true
});
// Interactive tooltip
createTippy('.interactive', {
content: document.querySelector('#tooltip-content'),
interactive: true,
trigger: 'click'
});
Toast Notifications
import {showToast} from './modules/features/toast.js';
// Success toast
showToast('Operation completed successfully', 'success');
// Error toast
showToast('An error occurred', 'error');
// Warning toast
showToast('Please review your changes', 'warning');
// Info toast
showToast('New version available', 'info');
// Custom duration
showToast('Auto-closing in 5 seconds', 'info', 5000);
Markdown Rendering
import {renderMarkdown} from './modules/features/markup.js';
const markdown = '# Heading\n\nParagraph with **bold** text.';
const html = await renderMarkdown(markdown);
document.querySelector('#content').innerHTML = html;
Features:
- GitHub-flavored markdown
- Syntax highlighting
- Math rendering (KaTeX)
- Mermaid diagrams
- Task lists
- Emoji support
Mermaid Diagrams
import {renderMermaid} from './modules/features/mermaid.js';
const diagramCode = `
graph TD
A[Start] --> B[Process]
B --> C[End]
`;
await renderMermaid('#diagram-container', diagramCode);
SortableJS Integration
import Sortable from 'sortablejs';
const projectBoard = document.querySelector('#project-board');
Sortable.create(projectBoard, {
animation: 150,
handle: '.card-handle',
onEnd: (event) => {
const cardId = event.item.dataset.cardId;
const newPosition = event.newIndex;
// Update card position via API
fetch(`/api/v1/projects/cards/${cardId}/move`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({position: newPosition})
});
}
});
Error Codes
GitCaddy uses standard HTTP status codes with detailed error responses.
HTTP Status Codes
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 204 | No Content | Request succeeded with no response body |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Authentication required |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Resource conflict (e.g., duplicate name) |
| 422 | Unprocessable Entity | Validation error |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
| 503 | Service Unavailable | Service temporarily unavailable |
Error Response Format
{
"message": "Human-readable error message",
"errors": [
{
"field": "email",
"message": "Email is required"
}
],
"url": "https://docs.gitcaddy.example.com/api/errors/validation"
}
Common Error Codes
Authentication Errors:
{
"message": "Unauthorized: Invalid or expired token",
"code": "INVALID_TOKEN"
}
Validation Errors:
{
"message": "Validation failed",
"errors": [
{
"field": "name",
"message": "Repository name already exists"
},
{
"field": "description",
"message": "Description must be less than 500 characters"
}
]
}
Permission Errors:
{
"message": "Forbidden: You do not have permission to perform this action",
"required_permission": "admin"
}
Rate Limit Errors:
{
"message": "API rate limit exceeded",
"limit": 5000,
"remaining": 0,
"reset": "2024-01-20T11:00:00Z"
}
Resource Not Found:
{
"message": "Repository not found",
"resource": "repository",
"id": "username/nonexistent-repo"
}
Rate Limiting
GitCaddy implements rate limiting to prevent abuse.
Rate Limit Headers
All API responses include rate limit information:
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
X-RateLimit-Reset: 1705750800
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests per hour |
X-RateLimit-Remaining |
Remaining requests in current window |
X-RateLimit-Reset |
Unix timestamp when limit resets |
Rate Limits by Authentication
| Authentication | Requests/Hour |
|---|---|
| Unauthenticated | 60 |
| Authenticated (PAT) | 5,000 |
| OAuth Application | 5,000 |
| Enterprise License | 15,000 |
Handling Rate Limits
async function makeAPIRequest(url) {
const response = await fetch(url, {
headers: {
'Authorization': 'token YOUR_TOKEN'
}
});
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
if (response.status === 429) {
const resetDate = new Date(reset * 1000);
const waitTime = resetDate - new Date();
console.log(`Rate limited. Retry after ${waitTime}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
return makeAPIRequest(url); // Retry
}
if (remaining < 100) {
console.warn(`Low rate limit: ${remaining} requests remaining`);
}
return response.json();
}
Webhooks
GitCaddy can send HTTP POST requests to external URLs when events occur.
Creating Webhooks
Via API:
POST /api/v1/repos/{owner}/{repo}/hooks
Request Body:
{
"type": "gitea",
"config": {
"url": "https://example.com/webhook",
"content_type": "json",
"secret": "webhook_secret"
},
"events": [
"push",
"pull_request",
"issues",
"issue_comment",
"release"
],
"active": true
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | Webhook type: gitea, gogs, slack, discord |
config.url |
string | Yes | Webhook URL |
config.content_type |
string | No | Content type: json, form |
config.secret |
string | No | Secret for signature verification |
events |
array | Yes | Events to trigger webhook |
active |
boolean | No | Enable webhook (default: true) |
Webhook Events
| Event | Description |
|---|---|
push |
Git push to repository |
create |
Branch or tag created |
delete |
Branch or tag deleted |
fork |
Repository forked |
issues |
Issue opened, closed, edited |
issue_comment |
Comment on issue |
pull_request |
PR opened, closed, merged, edited |
pull_request_review |
PR review submitted |
pull_request_review_comment |
Comment on PR review |
release |
Release published |
repository |
Repository created, deleted |
wiki |
Wiki page created, edited |
Webhook Payload
Push Event:
{
"ref": "refs/heads/main",
"before": "abc123def456",
"after": "def456ghi789",
"compare_url": "https://gitcaddy.example.com/username/repo/compare/abc123...def456",
"commits": [
{
"id": "def456ghi789",
"message": "Fix bug in authentication",
"url": "https://gitcaddy.example.com/username/repo/commit/def456ghi789",
"author": {
"name": "Developer",
"email": "dev@example.com",
"username": "developer"
},
"committer": {
"name": "Developer",
"email": "dev@example.com",
"username": "developer"
},
"timestamp": "2024-01-20T10:00:00Z",
"added": ["new-file.js"],
"removed": [],
"modified": ["existing-file.js"]
}
],
"repository": {
"id": 1,
"name": "repo",
"full_name": "username/repo",
"html_url": "https://gitcaddy.example.com/username/repo",
"private": false,
"owner": {
"id": 1,
"login": "username",
"full_name": "User Name"
}
},
"pusher": {
"id": 1,
"login": "username",
"full_name": "User Name"
},
"sender": {
"id": 1,
"login": "username",
"full_name": "User Name"
}
}
Pull Request Event:
{
"action": "opened",
"number": 1,
"pull_request": {
"id": 1,
"number": 1,
"user": {
"id": 2,
"login": "contributor"
},
"title": "Add new feature",
"body": "Description of changes",
"state": "open",
"html_url": "https://gitcaddy.example.com/username/repo/pulls/1",
"diff_url": "https://gitcaddy.example.com/username/repo/pulls/1.diff",
"patch_url": "https://gitcaddy.example.com/username/repo/pulls/1.patch",
"merged": false,
"mergeable": true,
"base": {
"label": "main",
"ref": "main",
"sha": "abc123"
},
"head": {
"label": "contributor:feature",
"ref": "feature",
"sha": "def456"
},
"created_at": "2024-01-20T10:00:00Z",
"updated_at": "2024-01-20T10:00:00Z"
},
"repository": {
"id": 1,
"name": "repo",
"full_name": "username/repo"
},
"sender": {
"id": 2,
"login": "contributor"
}
}
Webhook Security
Signature Verification:
GitCaddy signs webhook payloads with HMAC-SHA256 using the configured secret.
X-Gitea-Signature: sha256=abc123def456...
Verification Example (Node.js):
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(payload);
const calculatedSignature = 'sha256=' + hmac.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(calculatedSignature)
);
}
// Express middleware
app.post('/webhook', (req, res) => {
const signature = req.headers['x-gitea-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process webhook
res.status(200).send('OK');
});
Testing Webhooks
Manual Test:
curl -X POST https://gitcaddy.example.com/api/v1/repos/username/repo/hooks/1/test \
-H "Authorization: token YOUR_TOKEN"
View Webhook Deliveries:
GET /api/v1/repos/{owner}/{repo}/hooks/{id}/deliveries
Response:
[
{
"id": 1,
"uuid": "abc-123-def-456",
"url": "https://example.com/webhook",
"request": {
"headers": {
"Content-Type": "application/json",
"X-Gitea-Event": "push",
"X-Gitea-Signature": "sha256=..."
},
"body": "{...}"
},
"response": {
"status": 200,
"headers": {},
"body": "OK"
},
"delivered_at": "2024-01-20T10:00:00Z",
"duration": 0.123
}
]
Code Examples
Complete Repository Workflow
// Create repository
async function createRepository(name, description) {
const response = await fetch('https://gitcaddy.example.com/api/v1/user/repos', {
method: 'POST',
headers: {
'Authorization': 'token YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: name,
description: description,
private: false,
auto_init: true,
license: 'MIT'
})
});
return response.json();
}
// Add file to repository
async function addFile(owner, repo, path, content, message) {
const encodedContent = btoa(content);
const response = await fetch(
`https://gitcaddy.example.com/api/v1/repos/${owner}/${repo}/contents/${path}`,
{
method: 'POST',
headers: {
'Authorization': 'token YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: encodedContent,
message: message,
branch: 'main'
})
}
);
return response.json();
}
// Create pull request
async function createPullRequest(owner, repo, title, head, base) {
const response = await fetch(
`https://gitcaddy.example.com/api/v1/repos/${owner}/${repo}/pulls`,
{
method: 'POST',
headers: {
'Authorization': 'token YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: title,
head: head,
base: base,
body: 'Please review these changes'
})
}
);
return response.json();
}
// Usage
(async () => {
const repo = await createRepository('my-project', 'My awesome project');
console.log('Repository created:', repo.html_url);
const file = await addFile(
'username',
'my-project',
'src/index.js',
'console.log("Hello World");',
'Add index.js'
);
console.log('File added:', file.commit.sha);
const pr = await createPullRequest(
'username',
'my-project',
'Add feature',
'feature-branch',
'main'
);
console.log('Pull request created:', pr.html_url);
})();
Issue Management
import requests
class GitCaddyClient:
def __init__(self, base_url, token):
self.base_url = base_url
self.headers = {
'Authorization': f'token {token}',
'Content-Type': 'application/json'
}
def create_issue(self, owner, repo, title, body, labels=None):
url = f'{self.base_url}/api/v1/repos/{owner}/{repo}/issues'
data = {
'title': title,
'body': body
}
if labels:
data['labels'] = labels
response = requests.post(url, json=data, headers=self.headers)
return response.json()
def add_comment(self, owner, repo, issue_number, comment):
url = f'{self.base_url}/api/v1/repos/{owner}/{repo}/issues/{issue_number}/comments'
data = {'body': comment}
response = requests.post(url, json=data, headers=self.headers)
return response.json()
def close_issue(self, owner, repo, issue_number):
url = f'{self.base_url}/api/v1/repos/{owner}/{repo}/issues/{issue_number}'
data = {'state': 'closed'}
response = requests.patch(url, json=data, headers=self.headers)
return response.json()
def track_time(self, owner, repo, issue_number, seconds):
url = f'{self.base_url}/api/v1/repos/{owner}/{repo}/issues/{issue_number}/times'
data = {'time': seconds}
response = requests.post(url, json=data, headers=self.headers)
return response.json()
# Usage
client = GitCaddyClient('https://gitcaddy.example.com', 'YOUR_TOKEN')
# Create issue
issue = client.create_issue(
'username',
'my-repo',
'Bug: Login not working',
'Users cannot log in with correct credentials',
labels=[1, 2] # bug, high-priority
)
print(f'Issue created: #{issue["number"]}')
# Add comment
comment = client.add_comment(
'username',
'my-repo',
issue['number'],
'Investigating the issue...'
)
# Track time (2 hours)
time_entry = client.track_time('username', 'my-repo', issue['number'], 7200)
print(f'Tracked {time_entry["time"]}s')
# Close issue
closed = client.close_issue('username', 'my-repo', issue['number'])
print(f'Issue closed: {closed["state"]}')
CI/CD Integration
# .gitcaddy/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
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 dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Get secrets from Vault
id: vault
uses: actions/vault-secrets@v1
with:
secrets: |
database_password
api_key
- name: Deploy
if: github.ref == 'refs/heads/main'
run: |
echo "Deploying with API key: ${{ steps.vault.outputs.api_key }}"
npm run deploy
env:
DATABASE_PASSWORD: ${{ steps.vault.outputs.database_password }}
API_KEY: ${{ steps.vault.outputs.api_key }}
Webhook Handler
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type PushEvent struct {
Ref string `json:"ref"`
Before string `json:"before"`
After string `json:"after"`
Repository struct {
Name string `json:"name"`
FullName string `json:"full_name"`
} `json:"repository"`
Pusher struct {
Login string `json:"login"`
} `json:"pusher"`
Commits []struct {
ID string `json:"id"`
Message string `json:"message"`
Author struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"author"`
} `json:"commits"`
}
func verifySignature(payload []byte, signature, secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(payload)
expectedMAC := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(signature), []byte(expectedMAC))
}
func handleWebhook(w http.ResponseWriter, r *http.Request) {
payload, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading request body", http.StatusBadRequest)
return
}
defer r.Body.Close()
signature := r.Header.Get("X-Gitea-Signature")
if !verifySignature(payload, signature, "webhook_secret") {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
event := r.Header.Get("X-Gitea-Event")
switch event {
case "push":
var pushEvent PushEvent
if err := json.Unmarshal(payload, &pushEvent); err != nil {
http.Error(w, "Error parsing JSON", http.StatusBadRequest)
return
}
log.Printf("Push to %s by %s", pushEvent.Repository.FullName, pushEvent.Pusher.Login)
log.Printf("Commits: %d", len(pushEvent.Commits))
for _, commit := range pushEvent.Commits {
log.Printf(" - %s: %s", commit.ID[:7], commit.Message)
}
case "pull_request":
log.Printf("Pull request event received")
default:
log.Printf("Unknown event: %s", event)
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Webhook processed")
}
func main() {
http.HandleFunc("/webhook", handleWebhook)
log.Println("Webhook server listening on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Package Publishing
#!/bin/bash
# publish-npm.sh - Publish npm package to GitCaddy registry
GITCADDY_URL="https://gitcaddy.example.com"
OWNER="username"
TOKEN="YOUR_TOKEN"
# Configure npm
npm config set registry "${GITCADDY_URL}/api/packages/${OWNER}/npm/"
npm config set "//${GITCADDY_URL#https://}/api/packages/${OWNER}/npm/:_authToken" "${TOKEN}"
# Update version
npm version patch
# Publish
npm publish
echo "Package published to GitCaddy registry"
# Dockerfile - Build and push Docker image to GitCaddy registry
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
# Build and push:
# docker build -t gitcaddy.example.com/username/myapp:latest .
# docker login gitcaddy.example.com
# docker push gitcaddy.example.com/username/myapp:latest
For additional support and documentation, visit the GitCaddy Documentation or join the community forum.