Move upload/delete forms outside main settings form to avoid invalid nested form HTML. Use form attribute on buttons and inputs to associate with hidden forms. Fixes HTML validation errors and potential browser quirks. Also replaces hardcoded border color with CSS variable for theme consistency. Affects brand logo/favicon and hero image upload sections.
Add PublicReleaseDownloads repository setting to allow direct release downloads without authentication for Limited visibility repos. Adds migration v369, checkbox in Advanced Settings (only shown for Limited repos with releases enabled), and updates attachment serving logic to check HasPublicReleases. Moves release download routes outside auth requirement when public downloads enabled. Complements existing pages config PublicReleases toggle.
Automatically categorize release attachments into Windows, macOS, Linux, Android, iOS, and Other sections based on filename patterns and extensions. Uses heuristics like file extensions (.exe, .dmg, .deb, .apk, .ipa), platform keywords (windows, darwin, linux, android, ios), and common naming conventions. Improves download UX by organizing files into logical platform groups with appropriate icons. Applies to all four page templates.
Replace .Author.Name with .Author.DisplayName in all page templates to show the user's display name instead of username for blog post authors. Affects all four landing page templates (bold-marketing, minimalist-docs, open-source-hero, saas-conversion). Consistent with user display name conventions elsewhere in the application.
Extract common image upload and delete logic into pagesUploadImage and pagesDeleteImage helper functions. Eliminates ~90 lines of duplicated code across logo, favicon, and hero image handlers. Uses function parameters for field-specific operations (get/set config fields, locale keys, file prefixes). Makes it easier to add new image upload fields in the future.
Allow public access to blog post featured images even when repository is private, if the post is published and blog is enabled. This supports public landing pages with blog sections that display featured images. Adds IsPublishedBlogFeaturedImage query and isBlogFeaturedImage check in attachment serving. Also removes redundant SafeHTML filter from blog content templates (already HTML-safe).
Add configurable gallery section that displays images from repository's .gallery folder on landing pages. Includes settings for enabled/disabled, headline, subheadline, max images (default 6), and grid columns (default 3). Reads captions from gallery.json metadata. Implements gallery rendering in all four page templates (bold-marketing, minimalist-docs, open-source-hero, saas-conversion). Integrates with existing gallery management feature.
Add ability to upload logo and favicon images directly instead of only using URLs. Images stored in repo-avatars storage with hash-based filenames (max 5 MB, JPG/PNG/WebP/GIF). Uploaded images take priority over URL fields. Includes upload/delete endpoints for both logo and favicon, UI with previews, and ResolvedLogoURL/ResolvedFaviconURL helper methods. Updates base_head template to use resolved favicon URL.
Add ability to upload hero images directly instead of only using URLs. Images are stored in repo-avatars storage with hash-based filenames (max 5 MB, JPG/PNG/WebP/GIF). Uploaded images take priority over URL field. Includes upload and delete endpoints, UI with preview, and ResolvedImageURL helper method. Improves UX by eliminating need for external image hosting.
Expand social link platform support from 5 to 16 platforms. Adds: Bluesky, Facebook, Instagram, Mastodon, Reddit, RSS, Substack, Threads, TikTok, and Twitch. Updates footer settings UI and all page templates (bold-marketing, minimalist-docs, open-source-hero, saas-conversion) with appropriate Octicon mappings for each platform.
Add OwnerDisplayName field to Repository model to allow custom display name for repository owner (e.g., "John Smith" instead of username). Used in license generation, social cards, and other public-facing contexts. Includes migration v368 to add column, UI in repository settings, and updates to license creation and social card rendering to use display name when available.
Add checkbox in pages SEO settings to use the repository's Media Kit social preview as the Open Graph image instead of a custom URL. When enabled, shows preview of the social card and uses /social-preview endpoint. Adds og:title, og:description, og:image, and twitter:card meta tags to pages base template. Improves social sharing integration with existing Media Kit feature.
Replace plain text input with interactive chip UI for SEO keywords in repository pages settings. Users can add keywords individually with validation, and remove them by clicking the × button. Backend now trims whitespace from keywords. Improves UX for managing keyword lists.
Ensure repository owner is loaded before rendering landing pages to prevent template errors when accessing .Repository.Owner.Name. Add error logging if owner loading fails.
Remove inline instruction prompts from experiment generation and analysis. These instructions are now defined in ABTestGeneratePlugin and ABTestAnalyzePlugin, eliminating duplication and improving maintainability.
Simplify AI content generation by delegating to plugin system:
- Remove inline prompt instructions (now in LandingPageContentPlugin)
- Add extractJSON helper to handle markdown-wrapped responses
- Hardcode CTA URLs to repo URL instead of relying on AI
- Apply JSON extraction to both content generation and translation
- Reduces code duplication and improves maintainability
Add "admin.dashboard.analyze_page_experiments" translation key across all 29 locales for the landing page A/B testing experiment analysis cron job in the admin dashboard.
Implement internationalization system for landing pages:
- Database model for storing language-specific translations
- Language configuration with default and enabled languages
- Language switcher in navigation across all templates
- Translation management UI in settings
- Support for 15 languages including English, Spanish, German, French, Japanese, Chinese
- Auto-detection and manual language selection
- AI-powered translation generation capability
Enable blog functionality on custom domains with dedicated views:
- Blog post detail page with markdown rendering
- Paginated blog list view
- Shared context setup for consistent navigation/footer
- Route handling for /blog and /blog/:id paths
- Template updates across all landing page themes
Add blog section configuration and rendering to landing pages. Includes:
- New BlogSectionConfig with headline, max posts, and excerpt options
- Logo source selection (URL, repo avatar, or org avatar)
- Recent blog posts display with featured images
- Navigation links to blog section
- Absolute repo URLs for custom domain support
Implement MCP tools for querying repository issues. list_issues supports pagination and state filtering (open/closed/all), while get_issue retrieves detailed information including body content and comments for a specific issue.
Allow private repositories to enable public release downloads on their landing pages. When enabled, unauthenticated users can download release attachments without accessing the repository. Adds download sections to all landing page templates with styling.
Add theme configuration options to control visibility of Licenses and API links in the footer. Also add authentication token to vault version API requests in build workflow to prevent rate limiting issues.
Move ShowFooterPoweredBy from static setting to dynamic theme configuration, allowing admins to toggle the "Powered by GitCaddy Server" footer message through the admin panel without restarting the server.
Add RELEASE_TOKEN to all checkout actions to enable access to private dependencies during CI builds. Fixes authentication issues when cloning vault and other private repositories.
Separate packages into PublicPackages and PrivatePackages arrays for template rendering. Add CanWritePackages flag to determine if viewer has permission to publish packages (admin, owner, or org team member with write access). Revert anonymous user 404 redirect to show proper error page.
Improve UX for unauthenticated visitors by redirecting them to the homepage instead of showing a 404 page. Authenticated users still see the standard 404 error page.
Set Private flag based on whether actor is present. When actor is nil (anonymous), Private must be false so SearchRepositoryCondition correctly filters to public repos only. Fixes repo count visibility for unauthenticated users.
Pass actor/doer to GetOrgOverviewStats to filter repository count based on user access rights. Replace CountRepositories with SearchRepository to respect permission checks. Prevents users from seeing total count of repos they cannot access.
Parse .gitsecrets-ignore file from commits to filter out known false positives during secret scanning. Matches entries by SHA-256 content hash (truncated to 16 chars) and pattern ID. Update push rejection message to guide users toward GitSecrets addon for managing ignored detections.
Update runner label matching to strip ":scheme" suffixes (e.g., ":host", ":docker") before comparison. This allows runners with "germany-linux:host" to match jobs with "runs-on: germany-linux" and vice versa.
Previously, exact label match was required, causing runners with scheme-qualified labels to fail matching jobs without schemes.
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.
Complete protocol versioning implementation on the server side, enabling forward-compatible plugin protocol evolution.
Server Changes:
- Send ProtocolVersion = 1 in InitializeRequest
- Store plugin's reported protocol version in ManagedPlugin
- Treat version 0 (pre-versioning plugins) as version 1
- Add SupportsProtocol() method to check before calling version-gated RPCs
- Log plugin's protocol version during initialization
Generated Code:
- Regenerate plugin.pb.go with protocol_version fields
- Add getter methods for new fields
Documentation:
- Add Protocol Versioning section to PLUGINS.md
- Explain version negotiation flow
- Document when plugins need to update vs. when they don't
- Add version history table (currently only v1)
- Update all example code to return protocol_version = 1
Benefits:
- Server can safely add new RPCs in future versions without breaking old plugins
- Plugins can detect newer servers and opt into advanced features
- Zero-value (0) provides backwards compatibility with pre-versioning plugins
- Clear upgrade path documented for plugin developers
This completes the protocol versioning feature started in the previous commit.
Add PLUGINS.md with complete documentation for building external GitCaddy plugins using the gRPC-based plugin protocol.
Documentation includes:
- Protocol overview and service definition
- Lifecycle diagram (Initialize → HealthCheck → OnEvent/HandleHTTP → Shutdown)
- Complete message reference for all 6 RPC methods
- Plugin manifest specification (routes, events, permissions, license tiers)
- Health monitoring and auto-restart behavior
- Configuration guide for external vs managed mode
- Transport details (h2c/HTTP2, gRPC wire format)
- Full working examples in Go, C#, and Python
- Debugging tips and common issues
Also updates README.md to reference the plugin guide and removes outdated Chinese translations (zh-cn, zh-tw) that were not being maintained.
This provides plugin developers with everything needed to build and deploy external services that integrate with GitCaddy's plugin framework.
Implement critical production readiness features for AI integration: per-request provider config, admin dashboard, workflow inspection, and plugin framework foundation.
Per-Request Provider Config:
- Add ProviderConfig struct to all AI request types
- Update queue to resolve provider/model/API key from cascade (repo > org > system)
- Pass resolved config to AI sidecar on every request
- Fixes multi-tenant issue where all orgs shared sidecar's hardcoded config
Admin AI Dashboard:
- Add /admin/ai page with sidecar health status
- Display global operation stats (total, 24h, success/fail/escalated counts)
- Show operations by tier, top 5 repos, token usage
- Recent operations table with repo, operation, status, duration
- Add GetGlobalOperationStats model method
Workflow Inspection:
- Add InspectWorkflow client method and types
- Implement workflow-inspect queue handler
- Add notifier trigger on workflow file push
- Analyzes YAML for syntax errors, security issues, best practices
- Returns structured issues with line numbers and suggested fixes
Plugin Framework (Phase 5 Foundation):
- Add external plugin config loading from app.ini
- Define ExternalPlugin interface and manager
- Add plugin.proto contract (Initialize, Shutdown, HealthCheck, OnEvent, HandleHTTP)
- Implement health monitoring with auto-restart for managed plugins
- Add event routing to subscribed plugins
- HTTP proxy support for plugin-served routes
This completes Tasks 1-4 from the production readiness plan and establishes the foundation for managed plugin lifecycle.
Significantly expand the AI features section of the README with comprehensive configuration and usage documentation.
New content includes:
- Detailed explanation of Tier 1 (light operations) vs Tier 2 (agent mode)
- Complete app.ini configuration reference with all AI settings
- Step-by-step setup guide (system → org → repo → runner)
- Configuration cascade explanation (repo > org > system)
- Built-in safety features (bot user, loop prevention, rate limits, escalation)
- Automatic operation triggers table
- Manual API trigger examples
- Operation history and audit log access
- Escalation workflow documentation
- V2 API configuration section
This provides users with everything needed to deploy and configure the AI features, from initial setup through advanced agent mode configuration.