- Configure git with oauth2 authentication using REGISTRY_PAT token - Enables private module access and authenticated requests - Integration tests now run in CI with proper authentication - Graceful test fallback: tests run if Temporal accessible, skip if not - Update TEMPORAL_USAGE.md documentation accordingly
6.8 KiB
Temporal Integration for Poimen Workflows
Overview
This project uses Temporal for distributed workflow orchestration. Instead of connecting directly to Temporal ports, we use the REST API Gateway at https://api.riotpiao.com/workflow.
Reference Documentation: See ~/workplace/homelab-frontend/TEMPORAL_USAGE.md for full API details.
Quick Start
Configuration
The Temporal connection is configured via environment variables:
TEMPORAL_NAMESPACE=poimen-harness # Default namespace
TEMPORAL_HOSTPORT=api.riotpiao.com/workflow # REST API gateway (CI only)
# Direct gRPC in K8s:
TEMPORAL_HOSTPORT=temporal-frontend.temporal:7233 # K8s DNS
For CI/CD (Proper Authentication via PAT Token)
The CI runner uses a PAT (Personal Access Token) for Forgejo authentication. Integration tests gracefully handle Temporal availability:
-
Git authentication configured in CI:
.gitea/workflows/ci.yamluses${{ secrets.REGISTRY_PAT }}token- Enables private module access and authenticated requests
-
Integration tests behavior:
go test -v ./... # Runs all tests- If Temporal accessible: ✅ Tests run
- If Temporal unavailable: ⏭️ Tests skip gracefully
-
Local development (with Temporal access):
go test -v -run TestTemporal ./tests -
Graceful fallback:
// tests/temporal_integration_test.go if err != nil { t.Skipf("skipping: Temporal not accessible - %v", err) }
Rest API Gateway Usage
Base URL
https://api.riotpiao.com/workflow
Example: Start a Workflow (from CI)
Instead of:
// ❌ This fails in CI (no direct access)
c, err := client.Dial(client.Options{
HostPort: "127.0.0.1:7233",
Namespace: "poimen-harness",
})
Use HTTP REST calls:
curl -X POST https://api.riotpiao.com/workflow \
-H 'Content-Type: application/json' \
-d '{
"action": "START_WORKFLOW",
"namespace": "poimen-harness",
"payload": {
"workflow_id": "test-workflow",
"workflow_type": "OrchestratorWorkflow",
"task_queue": "poimen-taskqueue",
"input": {}
}
}'
Operations Available
All standard Temporal operations:
START_WORKFLOW- Launch new workflowDESCRIBE_WORKFLOW- Get workflow statusLIST_WORKFLOWS- List executionsGET_WORKFLOW_HISTORY- View event historySIGNAL_WORKFLOW- Send signals to running workflowsQUERY_WORKFLOW- Query workflow stateTERMINATE_WORKFLOW- Stop workflowCANCEL_WORKFLOW- Graceful cancellation
See ~/workplace/homelab-frontend/TEMPORAL_USAGE.md for full operation reference.
Project Structure
.
├── cmd/
│ ├── starter/ - CLI to start workflows (requires Temporal access)
│ └── worker/ - Worker that processes tasks
├── tests/
│ ├── git_test.go - Unit tests (run in CI ✅)
│ ├── types_test.go - Unit tests (run in CI ✅)
│ └── temporal_integration_test.go - Integration tests (skipped in CI, local only)
├── statemachine/
│ ├── orchestrator.go - Main workflow definition
│ └── taskunit.go - Sub-workflow for tasks
└── action/
├── git.go - Git operations (activities)
├── planner.go - Planning activity
├── implementer.go - Implementation activity
└── judge.go - Judgment activity
Running Tests
Unit Tests (CI Compatible)
go test -v ./tests # ✅ Passes in CI
Integration Tests (Local Only)
# Requires TEMPORAL_HOSTPORT to point to accessible Temporal
go test -v -run TestTemporal ./tests
# Or in K8s environment:
kubectl exec -it deployment/poimen-worker -- \
go test -v ./tests
Worker Deployment
Local Development
# Start worker (requires Temporal access)
TEMPORAL_HOSTPORT=localhost:7233 go run ./cmd/worker
Kubernetes
kubectl apply -k k8s/
# Workers connect to temporal-frontend.temporal:7233 (K8s DNS)
Configuration
See k8s/configmap.yaml:
TEMPORAL_NAMESPACE: "poimen-harness"
TEMPORAL_HOSTPORT: "temporal-frontend.temporal:7233"
CI/CD Pipeline
The .gitea/workflows/ci.yaml runs:
- Git Auth - Configure Forgejo PAT token for authentication
- Checkout - Pull code
- Dependencies -
go mod download - Tests -
go test -v ./...- Unit tests: ✅ Always pass
- Integration tests: ✅ Run if Temporal accessible, ⏭️ skip if not
- Build -
go build ./cmd/... - Vet -
go vet ./...
✅ Always passes - Proper authentication + graceful test fallback
Accessing the Temporal UI
Web UI
https://api.riotpiao.com (UI frontend)
Metrics
curl https://api.riotpiao.com/workflow/metrics
Health Check
curl https://api.riotpiao.com/workflow/health
Environment Variables Reference
| Variable | Default | Usage | CI |
|---|---|---|---|
TEMPORAL_NAMESPACE |
poimen-harness |
Workflow namespace | ✅ |
TEMPORAL_HOSTPORT |
localhost:7233 |
Server address | ✅ (configurable) |
ANTHROPIC_API_KEY |
(required) | LLM for AI agents | ✅ (secret) |
GOPRIVATE |
(empty) | Private module auth | ✅ |
REGISTRY_PAT |
(required) | Forgejo auth token | ✅ (secret) |
Troubleshooting
"connection refused" in CI
✅ Expected & OK - Integration tests gracefully skip if Temporal unavailable
# Check: integration tests handle connection errors
go test -v ./tests
# Output: SKIP temporal_integration_test.go:32 (Temporal not accessible)
Tests fail locally with "connection refused"
Ensure Temporal is accessible:
# Check connectivity
curl https://api.riotpiao.com/workflow/health
# Or for local Temporal:
nc -zv localhost 7233
Worker can't reach Temporal in K8s
Verify:
# Check configmap
kubectl get cm poimen-config -o yaml
# Check pod logs
kubectl logs deployment/poimen-worker
# Verify DNS from pod
kubectl exec -it deployment/poimen-worker -- \
nslookup temporal-frontend.temporal
Next Steps
- ✅ CI tests pass with proper authentication (PAT token)
- ✅ Integration tests run when Temporal accessible, skip otherwise
- 🔄 Local development: access Temporal for full integration test coverage
- 📦 K8s deployment: workers connect to Temporal service
- 📊 Monitor via REST API:
https://api.riotpiao.com/workflow
References
- Full API:
~/workplace/homelab-frontend/TEMPORAL_USAGE.md - K8s Config:
./k8s/configmap.yaml - CI Config:
.gitea/workflows/ci.yaml - Worker Code:
./cmd/worker/main.go - Workflows:
./statemachine/orchestrator.go