259 lines
6.2 KiB
Markdown
259 lines
6.2 KiB
Markdown
# 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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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 (No Direct Access)
|
||
|
|
|
||
|
|
The CI runner **cannot directly access Temporal gRPC ports** (7233, 7234, 7235). Instead:
|
||
|
|
|
||
|
|
1. **Integration tests are skipped by default** in CI:
|
||
|
|
```bash
|
||
|
|
go test -v ./... # Skips integration tests
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **To enable them locally** (requires Temporal access):
|
||
|
|
```bash
|
||
|
|
go test -v -run TestTemporal ./tests
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **CI only runs unit tests** that don't require Temporal:
|
||
|
|
```go
|
||
|
|
// tests/temporal_integration_test.go
|
||
|
|
if testing.Short() {
|
||
|
|
t.Skip("skipping Temporal integration test: use -v to run")
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Rest API Gateway Usage
|
||
|
|
|
||
|
|
### Base URL
|
||
|
|
```
|
||
|
|
https://api.riotpiao.com/workflow
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example: Start a Workflow (from CI)
|
||
|
|
|
||
|
|
Instead of:
|
||
|
|
```go
|
||
|
|
// ❌ 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:
|
||
|
|
```bash
|
||
|
|
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 workflow
|
||
|
|
- `DESCRIBE_WORKFLOW` - Get workflow status
|
||
|
|
- `LIST_WORKFLOWS` - List executions
|
||
|
|
- `GET_WORKFLOW_HISTORY` - View event history
|
||
|
|
- `SIGNAL_WORKFLOW` - Send signals to running workflows
|
||
|
|
- `QUERY_WORKFLOW` - Query workflow state
|
||
|
|
- `TERMINATE_WORKFLOW` - Stop workflow
|
||
|
|
- `CANCEL_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)
|
||
|
|
```bash
|
||
|
|
go test -v ./tests # ✅ Passes in CI
|
||
|
|
```
|
||
|
|
|
||
|
|
### Integration Tests (Local Only)
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
```bash
|
||
|
|
# Start worker (requires Temporal access)
|
||
|
|
TEMPORAL_HOSTPORT=localhost:7233 go run ./cmd/worker
|
||
|
|
```
|
||
|
|
|
||
|
|
### Kubernetes
|
||
|
|
```bash
|
||
|
|
kubectl apply -k k8s/
|
||
|
|
# Workers connect to temporal-frontend.temporal:7233 (K8s DNS)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Configuration
|
||
|
|
See `k8s/configmap.yaml`:
|
||
|
|
```yaml
|
||
|
|
TEMPORAL_NAMESPACE: "poimen-harness"
|
||
|
|
TEMPORAL_HOSTPORT: "temporal-frontend.temporal:7233"
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## CI/CD Pipeline
|
||
|
|
|
||
|
|
The `.gitea/workflows/ci.yaml` runs:
|
||
|
|
|
||
|
|
1. **Checkout** - Pull code
|
||
|
|
2. **Dependencies** - `go mod download`
|
||
|
|
3. **Unit Tests** - `go test -v ./...` (integration tests skipped)
|
||
|
|
4. **Build** - `go build ./cmd/...`
|
||
|
|
5. **Vet** - `go vet ./...`
|
||
|
|
|
||
|
|
✅ **Passes without Temporal access** - All tests that run are unit tests only.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Accessing the Temporal UI
|
||
|
|
|
||
|
|
### Web UI
|
||
|
|
```
|
||
|
|
https://api.riotpiao.com (UI frontend)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Metrics
|
||
|
|
```bash
|
||
|
|
curl https://api.riotpiao.com/workflow/metrics
|
||
|
|
```
|
||
|
|
|
||
|
|
### Health Check
|
||
|
|
```bash
|
||
|
|
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 | ⚠️ Not in CI |
|
||
|
|
| `ANTHROPIC_API_KEY` | (required) | LLM for AI agents | ✅ (secret) |
|
||
|
|
| `GOPRIVATE` | (empty) | Private module auth | ✅ |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### "connection refused" in CI
|
||
|
|
✅ **Expected & OK** - Integration tests skip in CI
|
||
|
|
```bash
|
||
|
|
# Check: integration tests are skipped
|
||
|
|
go test -v ./tests
|
||
|
|
# Output: SKIP temporal_integration_test.go:31 (testing.Short() = true)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Tests fail locally with "connection refused"
|
||
|
|
Ensure Temporal is accessible:
|
||
|
|
```bash
|
||
|
|
# 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:
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
|
||
|
|
1. ✅ Unit tests pass in CI (no Temporal required)
|
||
|
|
2. 🔄 Local development: access Temporal for integration tests
|
||
|
|
3. 📦 K8s deployment: workers connect to Temporal service
|
||
|
|
4. 📊 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`
|