# GitOps: Woodpecker CI & Forgejo Integration This document describes how to use the `gitops` crate with **Woodpecker CI** and **Forgejo** for event-driven CI/CD orchestration. ## Overview **Woodpecker CI** and **Forgejo** form a powerful, self-hosted CI/CD stack that pairs perfectly with declarative GitOps automation: - **Forgejo**: Self-hosted Git repository management (fork of Gitea) - **Woodpecker CI**: Lightweight, open-source CI/CD platform - **GitOps**: Declarative rules engine for orchestrating both ## Architecture ``` ┌─────────────────┐ │ Forgejo │ │ (Git Host) │ └────────┬────────┘ │ Webhook │ (push, PR, tag) ▼ ┌──────────────────────────┐ │ GitOps Engine │ │ (Rule Processor) │ └────────┬────────────────┘ │ Triggers │ Pipelines ▼ ┌─────────────────┐ │ Woodpecker CI │ │ (CI/CD Runs) │ └────────┬────────┘ │ Webhook │ (success, failure) ▼ ┌──────────────────────────┐ │ Deploy/Notify │ │ (Actions) │ └──────────────────────────┘ ``` ## Providers ### Forgejo Provider Forgejo is Gitea-compatible and supports the same API structure. #### Configuration ```rust use gitops::provider::{ForgejoProvider, GitProvider}; // Create provider let provider = ForgejoProvider::with_token( "https://git.company.internal/api/v1".to_string(), "your-access-token".to_string(), ); // Or use environment variable let provider = ForgejoProvider::new("https://git.company.internal/api/v1".to_string()); ``` #### Environment Variables - `FORGEJO_TOKEN`: API access token for Forgejo - Supports both PAT (Personal Access Token) and OAuth tokens #### Supported Operations - Get repository information - List repositories - Register/delete webhooks - Create commit status checks - Read/list files from repository - Create and manage releases - Sync organization members (LDAP integration available) ### Woodpecker Provider Woodpecker provides a RESTful API for pipeline orchestration. #### Configuration ```rust use gitops::provider::WoodpeckerProvider; // Create provider let provider = WoodpeckerProvider::with_token( "https://ci.company.internal/api".to_string(), "your-api-token".to_string(), ); // Or use environment variable let provider = WoodpeckerProvider::new("https://ci.company.internal/api".to_string()); ``` #### Environment Variables - `WOODPECKER_TOKEN`: API token for Woodpecker #### Supported Operations - Get repository information - List repositories - Trigger pipeline runs - Get pipeline status and logs - Create commit status checks - Register webhooks for pipeline events ## Event Sources ### Forgejo Event Source Listens to Forgejo webhook events: ```rust use gitops::event::ForgejoEventSource; let source = ForgejoEventSource::new(); ``` Supported events: - `push`: Code push to any branch - `pull_request`: PR opened, closed, merged - `tag_create`: New tag created - `release`: Release published ### Woodpecker Event Source Listens to Woodpecker pipeline events: ```rust use gitops::event::WoodpeckerEventSource; let source = WoodpeckerEventSource::new(); ``` Supported events: - `pipeline_started`: Pipeline execution started - `pipeline_success`: Pipeline completed successfully - `pipeline_failure`: Pipeline failed - `pipeline_killed`: Pipeline was manually stopped ## Usage Examples ### Example 1: Auto-Deploy on Tag Push ```yaml rules: - name: "deploy-on-tag" when: event: "git" type: "tag_create" provider: "forgejo" matches: tag: "v[0-9]+(\\.[0-9]+){2}" then: action: "deploy" environment: "production" params: deployment_method: "kubernetes" version: "${GIT_TAG}" ``` ### Example 2: Trigger Woodpecker Pipeline ```yaml rules: - name: "trigger-ci-on-push" when: event: "git" type: "push" provider: "forgejo" matches: branch: "main" then: action: "trigger-pipeline" provider: "woodpecker" params: repo: "${GIT_REPO}" branch: "${GIT_BRANCH}" commit: "${GIT_COMMIT}" ``` ### Example 3: Deploy After Successful Pipeline ```yaml rules: - name: "deploy-after-build" when: event: "woodpecker" type: "pipeline_success" matches: branch: "develop" then: action: "deploy" environment: "staging" params: deployment_method: "kubernetes" namespace: "staging" ``` ### Example 4: Auto-Merge PR on CI Success ```yaml rules: - name: "auto-merge-develop-pr" when: event: "woodpecker" type: "pipeline_success" matches: trigger_event: "pull_request" target_branch: "develop" then: action: "merge-pr" params: provider: "forgejo" merge_method: "squash" delete_source_branch: true ``` ## Webhook Configuration ### Forgejo Webhook Setup 1. Go to Repository → Settings → Webhooks 2. Add webhook: - **Payload URL**: `https://gitops.internal/webhooks/forgejo` - **Content Type**: `application/json` - **Events**: Push, Pull Request, Tag Creation, Release - **Secret**: Set to `FORGEJO_WEBHOOK_SECRET` ### Woodpecker Webhook Setup 1. Go to Repository → Settings → Integrations 2. Add webhook: - **Webhook URL**: `https://gitops.internal/webhooks/woodpecker` - **Trigger on**: Pipeline events - **Secret**: Set to `WOODPECKER_WEBHOOK_SECRET` ## Complete Workflow Example ### Repository Structure ``` myrepo/ ├── .woodpecker.yaml # Woodpecker CI configuration ├── .forgejo/ # Forgejo-specific files │ └── issue_template/ # Issue templates ├── src/ ├── tests/ └── README.md ``` ### .woodpecker.yaml ```yaml pipeline: build: image: rust:1.75 commands: - cargo build --release when: event: [push, pull_request] test: image: rust:1.75 commands: - cargo test --all when: event: [push, pull_request] deploy-staging: image: alpine/k8s:latest commands: - kubectl set image deployment/app app=myrepo:${CI_COMMIT_SHA} -n staging when: event: push branch: develop deploy-production: image: alpine/k8s:latest commands: - kubectl set image deployment/app app=myrepo:${CI_COMMIT_SHA} -n production secrets: [KUBECONFIG] when: event: push branch: main ``` ### GitOps Rules ```yaml rules: # Build on push - name: "build-on-push" when: event: "git" type: "push" provider: "forgejo" then: action: "trigger-pipeline" provider: "woodpecker" # Deploy staging - name: "deploy-staging" when: event: "woodpecker" type: "pipeline_success" matches: branch: "develop" then: action: "deploy" environment: "staging" # Deploy production (with approval) - name: "deploy-production" when: event: "git" type: "tag_create" provider: "forgejo" then: action: "deploy" environment: "production" requires_approval: true approvers: - "product-owner@company.com" ``` ## Environment Variables Required environment variables: ```bash # Forgejo export FORGEJO_TOKEN="your-access-token" export FORGEJO_WEBHOOK_SECRET="webhook-secret" # Woodpecker export WOODPECKER_TOKEN="your-api-token" export WOODPECKER_WEBHOOK_SECRET="webhook-secret" # Notifications export SLACK_WEBHOOK="https://hooks.slack.com/services/..." # Kubernetes (for deployments) export KUBECONFIG="/path/to/kubeconfig" ``` ## Advanced Features ### 1. Repository Mirroring Mirror Forgejo repositories to backup or public providers: ```yaml rules: - name: "mirror-to-github" when: event: "git" type: "push" provider: "forgejo" matches: branch: "main" then: action: "mirror" params: destination: "github" repo: "myorg/myrepo" force_update: false ``` ### 2. Automatic Dependency Updates ```yaml rules: - name: "auto-update-deps" when: event: "schedule" matches: cron: "0 2 * * 0" # Weekly then: action: "create-pr" params: title: "[Chore] Update dependencies" branch: "chore/deps-update" ``` ### 3. Security Scanning ```yaml rules: - name: "security-scan" when: event: "schedule" matches: cron: "0 3 * * 1" # Weekly on Monday then: action: "trigger-pipeline" provider: "woodpecker" params: pipeline: "security-scan" ``` ### 4. LDAP/Active Directory Sync ```rust // Automatic synchronization of Forgejo users from LDAP let provider = ForgejoProvider::with_token( "https://git.company.internal/api/v1".to_string(), token, ); // Configure LDAP sync in Forgejo settings // gitops will maintain organization membership in sync ``` ## Troubleshooting ### Webhook Not Firing 1. Check webhook delivery in Forgejo: Settings → Webhooks → Recent Deliveries 2. Verify firewall allows `gitops.internal` from Forgejo 3. Check GitOps logs: `RUST_LOG=debug cargo run` ### Pipeline Not Triggering 1. Verify Woodpecker token has API access 2. Check Woodpecker repository settings are enabled 3. Ensure webhook secret is correctly configured ### Permission Errors 1. Verify token has necessary scopes: - Forgejo: `repo`, `admin:org` (if managing organizations) - Woodpecker: `repo`, `pipeline` 2. Check repository permissions in Forgejo ## Best Practices 1. **Token Rotation**: Rotate API tokens regularly 2. **Webhook Secrets**: Always use webhook secrets for security 3. **Rule Ordering**: Order rules by priority (higher first) 4. **Approval Gates**: Require approval for production deployments 5. **Monitoring**: Enable metrics and alerts for GitOps engine 6. **Backups**: Backup Forgejo repositories regularly 7. **Testing**: Test rules in staging before production ## Performance Considerations - Woodpecker pipelines run in parallel by default - Use `depends_on` in .woodpecker.yaml to control dependency - GitOps processes events sequentially (configurable concurrency) - Webhook delivery is retried 3 times with exponential backoff ## Security Considerations 1. **Secrets Management**: Never commit tokens; use environment variables 2. **Webhook Validation**: Always validate webhook signatures 3. **RBAC**: Use Forgejo and Woodpecker RBAC features 4. **Network Isolation**: Keep internal services behind VPN/firewall 5. **Audit Logs**: Enable audit logging in Forgejo and Woodpecker ## See Also - [Examples](../../examples/gitops-woodpecker.yaml) - [Examples](../../examples/gitops-forgejo.yaml) - [Examples](../../examples/gitops-woodpecker-forgejo.yaml) - [Main GitOps Documentation](README.md)