Git Connector
Git Connector
Section titled “Git Connector”Git Connector (Express) synchronizes Strapi organization and user events to Gitea (git hosting), creating repositories, managing permissions, and syncing SSH keys.
Key Facts
Section titled “Key Facts”- Port: 3002
- Tech: Express, TypeScript, Axios
- Messaging: RabbitMQ (
git.eventsexchange) - Target: Gitea Toolbox (9023) + Gitea Apps (9034)
- Logging: Winston
Purpose
Section titled “Purpose”Git Connector bridges Strapi events and Gitea:
- User Created → Create Gitea user
- Organization Created → Create Gitea organization
- Member Added → Add user to org in Gitea
- SSH Key Changed → Update Gitea SSH keys
- Repository Sync → Mirror templates from Toolbox to Apps
Architecture
Section titled “Architecture”Two Gitea Instances
Section titled “Two Gitea Instances”| Instance | Port | Purpose | Database |
|---|---|---|---|
| Toolbox | 9023 | System repos, templates, shared tools | Shared MySQL (3308) |
| Apps | 9034 | User/org repos, applications | Shared MySQL (3308) |
| SSH | 9022 (Toolbox), 9033 (Apps) | Git over SSH | — |
Git Connector manages both instances with separate API calls.
Sync Flow
Section titled “Sync Flow”Strapi event (org.create) ↓RabbitMQ: org.events (routing key: create) ↓Git Connector consumes event ├─ Extract organization data ├─ Create org in Toolbox (POST /api/v1/orgs) ├─ Create org in Apps (POST /api/v1/orgs) └─ Sync members (add users to org in both instances) ↓Webhook back to Strapi (optional, for audit) ↓Frontend sees organization ready for Git operationsEvent Handling
Section titled “Event Handling”Organization Events
Section titled “Organization Events”| Event | Action |
|---|---|
org.create | Create Gitea org in Toolbox + Apps |
org.update | Update Gitea org name/description |
org.delete | Delete Gitea org (soft delete if repos exist) |
Member Events
Section titled “Member Events”| Event | Action |
|---|---|
org.member.added | Add user to Gitea org |
org.member.removed | Remove user from Gitea org |
org.member.role.changed | Update Gitea team (admin/member) |
User Events
Section titled “User Events”| Event | Action |
|---|---|
user.create | Create Gitea user |
user.update | Update username/email |
user.ssh-key.added | Add SSH public key to Gitea |
user.ssh-key.removed | Remove SSH key from Gitea |
Configuration
Section titled “Configuration”.env variables:
# Gitea instancesGITEA_TOOLBOX_URL=http://gitea-toolbox:3000GITEA_TOOLBOX_ADMIN_TOKEN=<token>
GITEA_APPS_URL=http://gitea-apps:3000GITEA_APPS_ADMIN_TOKEN=<token>
# RabbitMQRABBITMQ_URL=amqp://admin:admin@sencai-mq:5672
# PortPORT=3002
# LoggingLOG_LEVEL=infoGitea Admin Token
Section titled “Gitea Admin Token”To create admin token:
- SSH into Gitea container:
docker exec -it gitea-toolbox bash - Run:
gitea admin user change-password admin --password <newpass> - Login to Gitea UI:
http://localhost:9023 - Settings → Applications → Generate new token
- Copy token and set in
.env
Or use Gitea CLI:
docker exec gitea-toolbox gitea admin user change-password admin --password admindocker exec gitea-toolbox gitea admin user generate-access-token -u admin -n sencaiProvisioning
Section titled “Provisioning”POST /org/provision creates a Gitea organisation in the Apps instance and registers the necessary team structure. It does not create any default repositories — no policies, config, or infrastructure repos are created automatically. Repository creation is always an explicit user action via the frontend or a direct API call.
HTTP API
Section titled “HTTP API”All endpoints are served on port 3002. Endpoints under /org/ require the X-Service-Secret header. For the complete endpoint list, see git-connector/CLAUDE.md.
Infrastructure
Section titled “Infrastructure”| Method | Path | Description |
|---|---|---|
GET | /health | Health check — Gitea Toolbox + Apps connectivity |
GET | /status | Instance status and statistics |
POST | /sync | Manual sync trigger |
GET | /queue/stats | RabbitMQ queue statistics |
POST | /cleanup/duplicates | Remove duplicate repository records in Strapi |
POST | /webhooks/repository | Gitea inbound webhook (requires WEBHOOK_ENABLED) |
Provisioning
Section titled “Provisioning”| Method | Path | Description |
|---|---|---|
POST | /org/provision | Create Gitea organisation (no default repos created) |
DELETE | /org/:slug/teardown | Archive organisation — all repos go read-only |
GET | /org/:slug/repos | List organisation repositories |
POST | /org/:slug/repos | Create a new repository |
GET | /org/:slug/packages | List packages (container, helm, generic, npm, pypi) |
GET | /org/:slug/ci | List workflow runs (Gitea Actions API) |
GET | /org/:slug/mirrors | List mirror repositories |
POST | /org/:slug/mirrors | Create a mirror repository |
DELETE | /org/:slug/mirrors/:repoName | Delete a mirror repository |
POST | /org/:slug/tokens | Create personal access token for an org member |
Repositories
Section titled “Repositories”| Method | Path | Description |
|---|---|---|
GET | /org/:slug/repo/:repo | Repository detail |
DELETE | /org/:slug/repo/:repo | Delete repository |
PUT | /org/:slug/repo/:repo | Update repository settings (name, description, private, has_issues, website) |
GET | /org/:slug/repo/:repo/branches | List branches |
GET | /org/:slug/repo/:repo/commits | Recent commits (query: limit, max 50) |
GET | /org/:slug/repo/:repo/issues | List issues (query: state, limit) |
Webhooks
Section titled “Webhooks”| Method | Path | Description |
|---|---|---|
GET | /org/:slug/repo/:repo/webhooks | List repository webhooks |
POST | /org/:slug/repo/:repo/webhooks | Create webhook (body: url, secret, events, active) |
DELETE | /org/:slug/repo/:repo/webhooks/:id | Delete webhook |
Deploy Keys
Section titled “Deploy Keys”| Method | Path | Description |
|---|---|---|
GET | /org/:slug/repo/:repo/keys | List deploy keys |
POST | /org/:slug/repo/:repo/keys | Add deploy key (body: title, key, read_only) |
DELETE | /org/:slug/repo/:repo/keys/:id | Delete deploy key |
Secrets & Variables (Actions)
Section titled “Secrets & Variables (Actions)”| Method | Path | Description |
|---|---|---|
GET | /org/:slug/repo/:repo/secrets | List Actions secrets |
PUT | /org/:slug/repo/:repo/secrets/:name | Create or update secret (body: data) |
DELETE | /org/:slug/repo/:repo/secrets/:name | Delete secret |
GET | /org/:slug/repo/:repo/variables | List Actions variables |
PUT | /org/:slug/repo/:repo/variables/:name | Create or update variable (body: value) |
DELETE | /org/:slug/repo/:repo/variables/:name | Delete variable |
| Method | Path | Description |
|---|---|---|
GET | /org/:slug/repo/:repo/tree | Directory tree (query: path, ref — default HEAD) |
GET | /org/:slug/repo/:repo/content | Raw file content (query: path required, ref) |
Gitea Actions
Section titled “Gitea Actions”Gitea Actions is enabled via the [actions] section in app.ini:
[actions]ENABLED = trueWORKFLOW_DIRS = .sencai/workflows,.gitea/workflows,.github/workflowsThe .sencai/workflows/ directory is checked first — it is the recommended location for Sencai-native workflow files. The .gitea/workflows/ and .github/workflows/ directories are supported for compatibility with existing pipelines.
Limitations:
- Mirror repositories do not trigger Actions. When a mirror is synced, Gitea does not generate a
pushevent, soon: pushworkflows will not fire. Useon: scheduleoron: workflow_dispatchinstead. - Runners must be registered before any workflow can execute. Queued runs wait indefinitely until a matching runner connects.
API Endpoints (legacy section)
Section titled “API Endpoints (legacy section)”Health
Section titled “Health”GET /health
Response:{ "status": "up", "gitea": { "toolbox": "connected", "apps": "connected" }}Webhook (from RabbitMQ consumer)
Section titled “Webhook (from RabbitMQ consumer)”POST /api/webhook (internal, no direct access needed)Trigger Sync
Section titled “Trigger Sync”POST /api/sync/:organisationId
Response:{ "status": "synced", "organisation": "org-name", "toolbox": "created", "apps": "created"}Gitea API Operations
Section titled “Gitea API Operations”Git Connector calls Gitea API (v1):
Create Organization
Section titled “Create Organization”POST http://gitea-toolbox:3000/api/v1/orgsAuthorization: token <ADMIN_TOKEN>
{ "username": "org-name", "full_name": "Organization Name", "description": "Org description", "website": "https://sencai.space", "location": "Remote"}Add User to Organization
Section titled “Add User to Organization”POST http://gitea-toolbox:3000/api/v1/orgs/org-name/teamsAuthorization: token <ADMIN_TOKEN>
{ "name": "Developers", "permission": "write", # or "read", "admin" "includes_all_repositories": true}Create SSH Key for User
Section titled “Create SSH Key for User”POST http://gitea-toolbox:3000/api/v1/user/keysAuthorization: token <USER_TOKEN>
{ "title": "My SSH Key", "key": "ssh-rsa AAAAB3...", "read_only": false}RabbitMQ Events
Section titled “RabbitMQ Events”Git Connector consumes from git.events and org.events exchanges.
Example event payload:
{ "event": "org.create", "organisation": { "id": 1, "name": "acme-corp", "description": "Acme AI Team", "ownerId": 10 }, "timestamp": "2024-01-01T12:00:00Z"}Logging
Section titled “Logging”# View logsdocker logs -f git-connector
# Example output:2024-01-01T12:00:00Z [INFO] Received event: org.create2024-01-01T12:00:00Z [INFO] Creating Gitea org: acme-corp in Toolbox2024-01-01T12:00:01Z [INFO] Creating Gitea org: acme-corp in Apps2024-01-01T12:00:02Z [INFO] Organization synced successfullyTroubleshooting
Section titled “Troubleshooting”Q: “Gitea connection refused”
A: Gitea not running or not accessible:
docker logs gitea-toolboxdocker logs gitea-apps
# Ensure git profile is running: ./run-local.sh gitQ: “Invalid admin token”
A: Token is expired or incorrect. Generate new token in Gitea UI (Settings → Applications).
Q: Organization not created in Gitea
A: Check Git Connector logs for errors. Verify:
- RabbitMQ is running:
docker logs sencai-mq - Event is published: Check RabbitMQ UI (localhost:15672)
- Git Connector is consuming:
docker logs git-connector
Q: SSH keys not syncing
A: Verify:
- SSH key format is valid (starts with
ssh-rsaorssh-ed25519) - User exists in Gitea
- User token has write permission
Q: “User already exists” error
A: User might already exist in Gitea from previous sync. Idempotency check may need improvement.
Q: Can’t push to Gitea repo via SSH
A: Verify:
- SSH key is added to Gitea user
- SSH port (9022 for Toolbox, 9033 for Apps) is open
- Git URL uses correct format:
git@localhost:orgname/reponame.git