yao/cmd/ci-token/main.go
Max c7b36aa3b5 feat(workflows): add MySQL and PostgreSQL configurations to unit test workflow
- Introduced MySQL and PostgreSQL environment variables in the unit test workflow for better database integration during testing.
- Configured MySQL and PostgreSQL services in the workflow to ensure proper database connectivity and health checks.
- Updated the sandbox-v2 environment file to include database connection details for local testing.

Made-with: Cursor
2026-03-12 20:49:34 +08:00

91 lines
2.4 KiB
Go

//go:build ci
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"time"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/engine"
"github.com/yaoapp/yao/openapi/oauth"
)
func main() {
appPath := flag.String("app", envOr("YAO_CI_APP_PATH", "."), "Yao application directory")
clientID := flag.String("client-id", envOr("YAO_CI_OAUTH_CLIENT_ID", "ci-tai"), "OAuth client ID embedded in token")
subject := flag.String("subject", envOr("YAO_CI_OAUTH_SUBJECT", "ci-tai"), "JWT subject claim")
scope := flag.String("scope", envOr("YAO_CI_OAUTH_SCOPE", "tai:tunnel"), "Token scope (space-separated)")
ttl := flag.String("ttl", envOr("YAO_CI_OAUTH_TTL", "24h"), "Token TTL (e.g. 1h, 24h, 168h)")
userID := flag.String("user-id", envOr("YAO_CI_OAUTH_USER_ID", ""), "User ID claim")
teamID := flag.String("team-id", envOr("YAO_CI_OAUTH_TEAM_ID", ""), "Team ID claim")
flag.Parse()
root, err := filepath.Abs(*appPath)
if err != nil {
fmt.Fprintf(os.Stderr, "ci-token: invalid app path: %v\n", err)
os.Exit(1)
}
if err := os.Chdir(root); err != nil {
fmt.Fprintf(os.Stderr, "ci-token: chdir %s: %v\n", root, err)
os.Exit(1)
}
savedStdout := os.Stdout
os.Stdout, _ = os.Open(os.DevNull)
config.Conf = config.LoadFrom(filepath.Join(root, ".env"))
config.Conf.Root = root
cfg := config.Conf
cfg.Session.IsCLI = true
warnings, err := engine.Load(cfg, engine.LoadOption{Action: "run"})
os.Stdout = savedStdout
if err != nil {
fmt.Fprintf(os.Stderr, "ci-token: engine.Load failed: %v\n", err)
os.Exit(1)
}
for _, w := range warnings {
fmt.Fprintf(os.Stderr, "ci-token: warning [%s]: %v\n", w.Widget, w.Error)
}
if oauth.OAuth == nil {
fmt.Fprintln(os.Stderr, "ci-token: oauth service not initialized (openapi.Load may have failed)")
os.Exit(1)
}
dur, err := time.ParseDuration(*ttl)
if err != nil {
fmt.Fprintf(os.Stderr, "ci-token: invalid --ttl %q: %v\n", *ttl, err)
os.Exit(1)
}
expiresIn := int(dur.Seconds())
extraClaims := map[string]interface{}{}
if *userID != "" {
extraClaims["user_id"] = *userID
}
if *teamID != "" {
extraClaims["team_id"] = *teamID
}
token, err := oauth.OAuth.MakeAccessToken(*clientID, *scope, *subject, expiresIn, extraClaims)
if err != nil {
fmt.Fprintf(os.Stderr, "ci-token: MakeAccessToken failed: %v\n", err)
os.Exit(1)
}
fmt.Print(token)
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}