Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions .github/workflows/gateway-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: Gateway Checks

# Guards the gateway plugin on every change under gateway/:
# - go: build + vet + unit tests for the plugin packages (auth,
# adminapi, hooks, …). The root package is a Go plugin (no main
# func; -buildmode=plugin, CGO, pinned Bifrost checkout), so the
# plugin binary itself is only built by the Dockerfile — a plain
# `go build .` fails by design. ./internal/... is the compile
# surface that matters for review.
# - tygo-check: regenerates ui/src/api/types.ts from the Go structs
# in gateway/internal/adminapi and fails on any diff, so a Go
# response-shape change can't land without its committed TS
# counterpart (phase-8 ship gate; drift would silently break the
# dashboard's typed fetch layer).
# - ui: type-checks (tsc -b) and bundles the SPA, catching imports
# the regenerated types.ts no longer satisfies.

on:
pull_request:
paths:
- "gateway/**"
- ".github/workflows/gateway-check.yml"
push:
branches: [main]
paths:
- "gateway/**"
- ".github/workflows/gateway-check.yml"

jobs:
go:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: gateway
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: gateway/go.mod
cache-dependency-path: gateway/go.sum

- name: Build
run: go build ./internal/...

- name: Vet
run: go vet ./internal/...

- name: Test
run: go test ./internal/...

tygo-check:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: gateway
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: gateway/go.mod
cache-dependency-path: gateway/go.sum

# Pinned so the generated output is byte-stable — a tygo release
# changing its formatting would otherwise fail every PR. Bump in
# lockstep with the version noted in gateway/Makefile and
# gateway/tygo.yaml.
- name: Install tygo
run: go install github.com/gzuidhof/tygo@v0.2.21

- name: Check generated TS types are up to date
run: make tygo-check

ui:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: gateway
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
# package-lock.json is git-ignored for this SPA, so key the
# npm cache on package.json instead.
cache-dependency-path: gateway/internal/adminapi/ui/package.json

- name: Install SPA dependencies
run: make ui-install

- name: Type-check and build SPA
run: make ui-build
7 changes: 5 additions & 2 deletions gateway/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,13 @@ ui: ui-install ui-build

# ─── tygo (Go -> TS struct codegen) ───────────────────────────────────
#
# Install once per dev machine:
# go install github.com/gzuidhof/tygo@latest
# Install once per dev machine (CI pins the same version in
# .github/workflows/gateway-check.yml — bump both together):
# go install github.com/gzuidhof/tygo@v0.2.21

tygo:
@command -v tygo >/dev/null 2>&1 || { \
echo "tygo not found: go install github.com/gzuidhof/tygo@v0.2.21"; exit 1; }
tygo generate

# CI hook: regenerate, then fail the build if the diff is non-empty.
Expand Down
14 changes: 7 additions & 7 deletions gateway/internal/adminapi/evals.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ type evalRunRequest struct {
Agent string `json:"agent,omitempty"`
}

// evalRefResponse is the create/link acknowledgement.
type evalRefResponse struct {
// EvalRefResponse is the create/link acknowledgement.
type EvalRefResponse struct {
RefID string `json:"ref_id"`
Linked bool `json:"linked,omitempty"`
}
Expand Down Expand Up @@ -234,7 +234,7 @@ func (h *evalHandlers) createOrLinkForAgent(w http.ResponseWriter, r *http.Reque
writeError(w, http.StatusBadGateway, "catalog_write_failed", "neo4j write failed")
return
}
writeJSON(w, http.StatusOK, evalRefResponse{RefID: req.SetID, Linked: true})
writeJSON(w, http.StatusOK, EvalRefResponse{RefID: req.SetID, Linked: true})
return
}

Expand All @@ -243,7 +243,7 @@ func (h *evalHandlers) createOrLinkForAgent(w http.ResponseWriter, r *http.Reque
writeError(w, http.StatusBadRequest, "missing_field", "name (or set_id) is required")
return
}
var created evalRefResponse
var created EvalRefResponse
if err := h.hive.call(ctx, http.MethodPost, "/api/gateway/evals",
map[string]any{"name": req.Name, "description": req.Description}, &created); err != nil {
relayHiveError(w, err)
Expand All @@ -262,7 +262,7 @@ func (h *evalHandlers) createOrLinkForAgent(w http.ResponseWriter, r *http.Reque
"set created but linking to agent failed")
return
}
writeJSON(w, http.StatusOK, evalRefResponse{RefID: created.RefID})
writeJSON(w, http.StatusOK, EvalRefResponse{RefID: created.RefID})
}

// linkEdge MERGEs HiveAgent-[:HAS_EVAL_SET]->EvalSet and clears any
Expand Down Expand Up @@ -457,7 +457,7 @@ func (h *evalHandlers) createSet(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusBadRequest, "missing_field", "name is required")
return
}
var created evalRefResponse
var created EvalRefResponse
if err := h.hive.call(r.Context(), http.MethodPost, "/api/gateway/evals",
map[string]any{"name": req.Name, "description": req.Description}, &created); err != nil {
relayHiveError(w, err)
Expand Down Expand Up @@ -513,7 +513,7 @@ func (h *evalHandlers) createRequirement(w http.ResponseWriter, r *http.Request,
writeError(w, http.StatusBadRequest, "missing_field", "name is required")
return
}
var created evalRefResponse
var created EvalRefResponse
if err := h.hive.call(r.Context(), http.MethodPost,
"/api/gateway/evals/"+urlSeg(setID)+"/requirements", req, &created); err != nil {
relayHiveError(w, err)
Expand Down
Loading
Loading