Skip to content

Add forge instance entity#800

Open
gabriel-samfira wants to merge 8 commits into
cloudbase:mainfrom
gabriel-samfira:add-forge-instance-entity
Open

Add forge instance entity#800
gabriel-samfira wants to merge 8 commits into
cloudbase:mainfrom
gabriel-samfira:add-forge-instance-entity

Conversation

@gabriel-samfira

Copy link
Copy Markdown
Member

This change adds a new forge entity type along side Repository{}, Organization{} and Enterprise{} called ForgeInstance{}. This new entity type is available currently only on Gitea and possibly on Forgejo if we ever get around to adding it.

The new ForgeInstance{} entity requires gitea credentials that have rw access to the admin api. This feels a bit too much to allow GARM to have, but if instance level pools are required, it cannot be helped.

The API is similar to the other entity types. WebUI has been updated to accomodate the new ForgeInstance type, as has the CLI.

This was referenced Jun 30, 2026
Add webhook management (create, list, get, delete) and runner operations
(list, remove, registration token) at the Gitea instance level. These
use the Gitea admin API endpoints (/admin/hooks, /admin/actions/runners).

Also add SupportsInstancePools() method on EndpointType and the
MetricsLabelInstanceScope constant for metrics recording.
Add the ForgeInstance and ForgeInstanceEvent models with UUID primary key
and a unique index on endpoint_name. Add full CRUD operations modeled
after enterprises, with endpoint name cross-validation against credentials.

Add database migration 0003_forge_instances to create the new tables and
add forge_instance_id columns to pools and workflow_jobs.

Wire ForgeInstance into all entity type switches in pools, jobs, util
(hasGithubEntity, GetForgeEntity, AddEntityEvent, SetEntityPoolManagerStatus,
updateEntityCredentials).
Add ForgeInstance params type with GetEntity(), CreateForgeInstanceParams
with forge type validation, and ForgeInstancePoolManager interface.

Implement pool manager lifecycle (create, start, stop, retry) with
WebSocket event subscriptions and cache worker integration.

Add runner CRUD: create, list, get, update, delete forge instances,
plus pool and instance management. Wire webhook dispatch for system
hooks and add ForgeInstance to all entity type switches in pool manager,
watcher filters, metadata service name, and job association.

Remove unused FetchTools method from basePoolManager.
Add REST API endpoints for forge instance CRUD, pool management,
instance listing, and webhook install/uninstall/info under
/forge-instances/{forgeInstanceID}/...

Add garm-cli forge-instance command (add, list, show, update, delete)
with endpoint name or UUID resolution, --random-webhook-secret, and
--install-webhook support.

Add --forge-instance/-f flag to pool list and pool add commands.

Regenerate swagger spec and OpenAPI client.
Add Forge Instances section to sidebar navigation with list and detail
pages. The list page shows endpoint name with forge type icon,
credentials, pool balancing type, status, and CRUD actions. The detail
page shows entity information, pools, instances, and events with
real-time WebSocket updates.

Add CreateForgeInstanceModal with endpoint selector (Gitea only),
credentials selector, pool balancer type, agent mode, and webhook
secret auto-generation.

Update all entity type unions across components to include forge_instance.
Wire ForgeInstance into eager cache, WebSocket subscriptions, pool entity
resolution (getEntityName, getEntityType, getEntityUrl), CreatePoolModal
entity level selector, UpdatePoolModal agent mode lookup, and
EndpointCell clickable links.
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Preload the entity's Endpoint relation in listEntityPools so that
pools listed via entity-specific endpoints include endpoint info.

Update the hardcoded SQL query in TestListAllPoolsDBFetchErr to include
the new forge_instance_id column.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
@gabriel-samfira gabriel-samfira force-pushed the add-forge-instance-entity branch from 3a98410 to c87fc58 Compare June 30, 2026 09:19
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
@Infinoid

Copy link
Copy Markdown
Contributor

I've set up a test instance to try this out, but I'm unsure whether I set it up properly. Here are the steps I followed:

  • build docker image for gabriel-samfira/add-forge-instance-entity (commit eee6176), and push it somewhere my k8s cluster can see it
  • build test copy of cli tool
  • deploy docker image into test environment (via a temporary terraform workspace)
  • configure garm-cli to talk to test manager (add test [[manager]] to config.toml and set it as default)
  • set up garm-test service account in gitea
  • set up personal access token for garm-test service account, with admin:readwrite scope
  • update gitea config to add test instance's hostname to webhook.ALLOWED_HOST_LIST
  • ./garm-cli gitea endpoint create --name=gitea-test …
  • ./garm-cli gitea credentials add --name=token …
  • ./garm-cli forge-instance add --forge-type=gitea --credentials=token --endpoint=gitea-test --install-webhook --random-webhook-secret
  • ./garm-cli pool add --forge-instance=gitea-test --tags=garm-test …
  • add a descriptive name to the webhook in gitea (it was empty)
  • try to trigger a job that runs-on: garm-test

Does this look right? I'm seeing the test environment receive webhook notifications from gitea, but rejecting them. Logs:

time=2026-06-30T13:11:35.235Z level=ERROR msg="failed to find pool manager" error="error fetching repo: error fetching repo: not found" hook_target_type=repository
time=2026-06-30T13:11:35.235Z level=ERROR msg="got not found error from DispatchWorkflowJob. webhook not meant for us?" error="error fetching poolManager: error fetching repo: error fetching repo: not found"
time=2026-06-30T13:11:35.235Z level=INFO msg=access_log method=POST uri=/webhooks/404760f1-a6d2-47d3-9248-aea6b0da4756 user_agent=Go-http-client/1.1 ip=[2600:1f18:7bbe:ba49:87aa::9]:38818 code=200 bytes=0 request_time=2.114832ms
time=2026-06-30T13:11:36.763Z level=ERROR msg="failed to find pool manager" error="error fetching repo: error fetching repo: not found" hook_target_type=repository
time=2026-06-30T13:11:36.763Z level=ERROR msg="got not found error from DispatchWorkflowJob. webhook not meant for us?" error="error fetching poolManager: error fetching repo: error fetching repo: not found"
time=2026-06-30T13:11:36.763Z level=INFO msg=access_log method=POST uri=/webhooks/404760f1-a6d2-47d3-9248-aea6b0da4756 user_agent=Go-http-client/1.1 ip=[2600:1f18:7bbe:ba49:87aa::9]:38818 code=200 bytes=0 request_time=711.585µs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants