# Drop this in ANY Gitea repo at .gitea/workflows/adversarial-review.yml to turn # Gadfly on. The image holds all the logic; this stub just forwards the event # context. Advisory only — it never blocks a merge. # # Per-repo setup (no code changes needed): # secret OLLAMA_CLOUD_API_KEY your Ollama Cloud key # var OLLAMA_REVIEW_MODELS (optional) comma-separated model ids # var GADFLY_ALLOWED_USERS (optional) who may "@gadfly review"; empty = # any repo collaborator # GITEA_TOKEN is provided automatically; comments post as the gitea-actions user. name: Adversarial Review (Gadfly) on: pull_request: types: [opened, reopened, ready_for_review] issue_comment: types: [created] workflow_dispatch: inputs: pr_number: description: "PR number to review" required: true permissions: contents: read issues: write pull-requests: write concurrency: group: gadfly-${{ github.event.issue.number || github.event.pull_request.number || github.event.inputs.pr_number }} cancel-in-progress: true jobs: review: # Security: only trusted users may trigger a secret-bearing run via a PR # comment (pull_request + workflow_dispatch are already trusted). Replace the # username(s) below with your maintainers — keep them in sync with # GADFLY_ALLOWED_USERS (the in-container belt-and-suspenders check). if: >- github.event_name != 'issue_comment' || github.actor == 'your-username' runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: docker://gitea.stevedudenhoeffer.com/steve/gadfly:v1 env: GITEA_API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} OLLAMA_CLOUD_API_KEY: ${{ secrets.OLLAMA_CLOUD_API_KEY }} OLLAMA_REVIEW_MODELS: ${{ vars.OLLAMA_REVIEW_MODELS }} GADFLY_ALLOWED_USERS: ${{ vars.GADFLY_ALLOWED_USERS }} # Specialist suite (optional). Empty = default suite # (security,correctness,maintainability,performance,error-handling). # csv to choose; "all" for everything; or define custom ones via a repo # .gadfly.yml / GADFLY_SPECIALIST_. See README "Specialists". GADFLY_SPECIALISTS: ${{ vars.GADFLY_SPECIALISTS }} # Lens fan-out (optional; default 1 = lenses run sequentially within a # model). Raise it to run a model's lenses concurrently so each model # posts its comment sooner. Total in-flight requests = (models at once) # × (lenses at once), so to fan out without oversubscribing a backend, # keep its model cap low and raise its lens cap. Per-provider configurable # via GADFLY_PROVIDER_LENS_CONCURRENCY (same lanes as the model map): # GADFLY_PROVIDER_CONCURRENCY: "ollama-cloud=1,m1=1" # GADFLY_PROVIDER_LENS_CONCURRENCY: "ollama-cloud=3,m1=1" # GADFLY_LENS_CONCURRENCY: ${{ vars.GADFLY_LENS_CONCURRENCY }} # GADFLY_PROVIDER_LENS_CONCURRENCY: ${{ vars.GADFLY_PROVIDER_LENS_CONCURRENCY }} # --- Models & providers (optional; default = Ollama Cloud) ---------- # Gadfly is majordomo-powered, so it can target other backends. Set a # provider for bare model ids; point at a different endpoint with a # base URL; supply a key (or the provider's standard env var). Examples: # # Local Ollama daemon (no key): # GADFLY_PROVIDER: ollama # GADFLY_MODELS: qwen2.5-coder:7b # # GADFLY_BASE_URL: http://my-ollama-host:11434 # if not localhost # # OpenAI-compatible endpoint (incl. local Ollama's /v1): # GADFLY_PROVIDER: openai # GADFLY_BASE_URL: http://localhost:11434/v1 # GADFLY_MODELS: qwen2.5-coder:7b # # OpenAI / Anthropic / Google (supported via majordomo, UNTESTED — see README): # GADFLY_PROVIDER: openai # then set OPENAI_API_KEY below # OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # # Named endpoint aliases (reference as name/model in GADFLY_MODELS). # vars/secrets aren't auto-exposed, so map each one explicitly: # GADFLY_ENDPOINT_BIGBOX: ${{ vars.GADFLY_ENDPOINT_BIGBOX }} # "ollama|http://192.168.1.50:11434" # GADFLY_MODELS: bigbox/qwen2.5-coder:7b GADFLY_PROVIDER: ${{ vars.GADFLY_PROVIDER }} GADFLY_BASE_URL: ${{ vars.GADFLY_BASE_URL }} GADFLY_MODELS: ${{ vars.GADFLY_MODELS }} EVENT_NAME: ${{ github.event_name }} PR: ${{ github.event.pull_request.number || github.event.issue.number || github.event.inputs.pr_number }} PR_BRANCH: ${{ github.head_ref }} IS_DRAFT: ${{ github.event.pull_request.draft }} COMMENT_BODY: ${{ github.event.comment.body }} COMMENT_ID: ${{ github.event.comment.id }} ACTOR: ${{ github.actor }}