ci: add Gitea Actions workflow with gofmt and test jobs #10
@@ -0,0 +1,29 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fmt:
|
||||||
|
runs-on: linux
|
||||||
|
thuanle marked this conversation as resolved
Outdated
|
|||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
- run: |
|
||||||
|
out=$(gofmt -l .)
|
||||||
|
if [ -n "$out" ]; then
|
||||||
|
echo "Files not formatted:"
|
||||||
|
echo "$out"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: linux
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
- run: go test ./...
|
||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
"thuanle.me/claw-email-bridge/internal/config"
|
"thuanle.me/claw-email-bridge/internal/config"
|
||||||
"thuanle.me/claw-email-bridge/internal/database"
|
"thuanle.me/claw-email-bridge/internal/database"
|
||||||
"thuanle.me/claw-email-bridge/internal/logging"
|
"thuanle.me/claw-email-bridge/internal/logging"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Retry backoff schedule: 1s, 5s, 15s.
|
// Retry backoff schedule: 1s, 5s, 15s.
|
||||||
@@ -20,11 +20,11 @@ var retryBackoffs = []time.Duration{1 * time.Second, 5 * time.Second, 15 * time.
|
|||||||
|
|
||||||
// openClawRequest is the payload sent to OpenClaw API.
|
// openClawRequest is the payload sent to OpenClaw API.
|
||||||
type openClawRequest struct {
|
type openClawRequest struct {
|
||||||
Input string `json:"input"`
|
Input string `json:"input"`
|
||||||
SessionID string `json:"session_id"`
|
SessionID string `json:"session_id"`
|
||||||
History []historyEntry `json:"history,omitempty"`
|
History []historyEntry `json:"history,omitempty"`
|
||||||
CallbackURL string `json:"callback_url"`
|
CallbackURL string `json:"callback_url"`
|
||||||
Metadata map[string]string `json:"metadata"`
|
Metadata map[string]string `json:"metadata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type historyEntry struct {
|
type historyEntry struct {
|
||||||
|
|||||||
@@ -130,9 +130,9 @@ func TestDispatch_UsesCallbackBaseURL(t *testing.T) {
|
|||||||
defer mockServer.Close()
|
defer mockServer.Close()
|
||||||
|
|
||||||
cfg := &config.Config{
|
cfg := &config.Config{
|
||||||
OpenClawURL: mockServer.URL,
|
OpenClawURL: mockServer.URL,
|
||||||
ListenAddr: ":9999",
|
ListenAddr: ":9999",
|
||||||
CallbackBaseURL: "https://bridge.example.com/",
|
CallbackBaseURL: "https://bridge.example.com/",
|
||||||
}
|
}
|
||||||
|
|
||||||
task := &database.Task{
|
task := &database.Task{
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"gorm.io/gorm"
|
||||||
"thuanle.me/claw-email-bridge/internal/database"
|
"thuanle.me/claw-email-bridge/internal/database"
|
||||||
"thuanle.me/claw-email-bridge/internal/logging"
|
"thuanle.me/claw-email-bridge/internal/logging"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CallbackRequest is the payload received from OpenClaw.
|
// CallbackRequest is the payload received from OpenClaw.
|
||||||
|
|||||||
+11
-11
@@ -102,17 +102,17 @@ func defaultCallbackBaseURL(listenAddr string) string {
|
|||||||
// validate checks that all required configuration values are present.
|
// validate checks that all required configuration values are present.
|
||||||
func (c *Config) validate() error {
|
func (c *Config) validate() error {
|
||||||
required := map[string]string{
|
required := map[string]string{
|
||||||
"IMAP_HOST": c.IMAPHost,
|
"IMAP_HOST": c.IMAPHost,
|
||||||
"IMAP_PORT": c.IMAPPort,
|
"IMAP_PORT": c.IMAPPort,
|
||||||
"IMAP_USER": c.IMAPUser,
|
"IMAP_USER": c.IMAPUser,
|
||||||
"IMAP_PASS": c.IMAPPass,
|
"IMAP_PASS": c.IMAPPass,
|
||||||
"SMTP_HOST": c.SMTPHost,
|
"SMTP_HOST": c.SMTPHost,
|
||||||
"SMTP_PORT": c.SMTPPort,
|
"SMTP_PORT": c.SMTPPort,
|
||||||
"SMTP_USER": c.SMTPUser,
|
"SMTP_USER": c.SMTPUser,
|
||||||
"SMTP_PASS": c.SMTPPass,
|
"SMTP_PASS": c.SMTPPass,
|
||||||
"OPENCLAW_URL": c.OpenClawURL,
|
"OPENCLAW_URL": c.OpenClawURL,
|
||||||
"BRIDGE_CALLBACK_TOKEN": c.BridgeCallbackToken,
|
"BRIDGE_CALLBACK_TOKEN": c.BridgeCallbackToken,
|
||||||
"SYSTEM_EMAIL": c.SystemEmail,
|
"SYSTEM_EMAIL": c.SystemEmail,
|
||||||
}
|
}
|
||||||
|
|
||||||
var missing []string
|
var missing []string
|
||||||
|
|||||||
+14
-14
@@ -6,28 +6,28 @@ import (
|
|||||||
|
|
||||||
// Task status constants matching the requirement's state machine.
|
// Task status constants matching the requirement's state machine.
|
||||||
const (
|
const (
|
||||||
StatusIgnored = "IGNORED"
|
StatusIgnored = "IGNORED"
|
||||||
StatusReceived = "RECEIVED"
|
StatusReceived = "RECEIVED"
|
||||||
StatusAIProcessing = "AI_PROCESSING"
|
StatusAIProcessing = "AI_PROCESSING"
|
||||||
StatusCallbackDone = "CALLBACK_DONE"
|
StatusCallbackDone = "CALLBACK_DONE"
|
||||||
StatusSMTPRetrying = "SMTP_RETRYING"
|
StatusSMTPRetrying = "SMTP_RETRYING"
|
||||||
StatusCompleted = "COMPLETED"
|
StatusCompleted = "COMPLETED"
|
||||||
StatusFailed = "FAILED"
|
StatusFailed = "FAILED"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Task represents a single email processing unit tracked through the pipeline.
|
// Task represents a single email processing unit tracked through the pipeline.
|
||||||
type Task struct {
|
type Task struct {
|
||||||
ID uint `gorm:"primaryKey;autoIncrement"`
|
ID uint `gorm:"primaryKey;autoIncrement"`
|
||||||
TaskUUID string `gorm:"uniqueIndex;not null"`
|
TaskUUID string `gorm:"uniqueIndex;not null"`
|
||||||
ThreadID string `gorm:"index"`
|
ThreadID string `gorm:"index"`
|
||||||
MessageID string `gorm:"index"`
|
MessageID string `gorm:"index"`
|
||||||
Sender string
|
Sender string
|
||||||
Subject string
|
Subject string
|
||||||
BodyPlain string
|
BodyPlain string
|
||||||
AIResponse string
|
AIResponse string
|
||||||
Status string `gorm:"index;not null"`
|
Status string `gorm:"index;not null"`
|
||||||
AttemptOpenClaw int `gorm:"default:0"`
|
AttemptOpenClaw int `gorm:"default:0"`
|
||||||
AttemptSMTP int `gorm:"default:0"`
|
AttemptSMTP int `gorm:"default:0"`
|
||||||
LastError *string
|
LastError *string
|
||||||
NextRetryAt *time.Time
|
NextRetryAt *time.Time
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import (
|
|||||||
"github.com/emersion/go-imap/v2/imapclient"
|
"github.com/emersion/go-imap/v2/imapclient"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"golang.org/x/net/proxy"
|
"golang.org/x/net/proxy"
|
||||||
|
"gorm.io/gorm"
|
||||||
"thuanle.me/claw-email-bridge/internal/config"
|
"thuanle.me/claw-email-bridge/internal/config"
|
||||||
"thuanle.me/claw-email-bridge/internal/database"
|
"thuanle.me/claw-email-bridge/internal/database"
|
||||||
"thuanle.me/claw-email-bridge/internal/logging"
|
"thuanle.me/claw-email-bridge/internal/logging"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IMAPWatcher monitors an IMAP mailbox via IDLE and processes new emails.
|
// IMAPWatcher monitors an IMAP mailbox via IDLE and processes new emails.
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
"thuanle.me/claw-email-bridge/internal/config"
|
"thuanle.me/claw-email-bridge/internal/config"
|
||||||
"thuanle.me/claw-email-bridge/internal/database"
|
"thuanle.me/claw-email-bridge/internal/database"
|
||||||
"thuanle.me/claw-email-bridge/internal/logging"
|
"thuanle.me/claw-email-bridge/internal/logging"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Retry backoff schedule: 1s, 5s, 15s.
|
// Retry backoff schedule: 1s, 5s, 15s.
|
||||||
|
|||||||
Reference in New Issue
Block a user
runs-on: linux
Fixed — updated to
runs-on: linux. Thanks!