153 lines
4.1 KiB
Go
153 lines
4.1 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"kforge/internal/generator"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// ------------------------------------------------------------
|
|
// kforge gitea-actions
|
|
// ------------------------------------------------------------
|
|
|
|
var (
|
|
giteaActionsOutput string
|
|
giteaActionsBranch string
|
|
giteaActionsEnvs []string
|
|
)
|
|
|
|
var giteaActionsCmd = &cobra.Command{
|
|
Use: "gitea-actions",
|
|
Short: "Generate a Gitea Actions deploy workflow for this app",
|
|
Long: `Generates .gitea/workflows/deploy.yml that:
|
|
- Builds and pushes the Docker image on push to main
|
|
- Runs kforge validate
|
|
- Applies cluster secrets (idempotent)
|
|
- Generates manifests and applies them with kubectl
|
|
- Rolls out the deployment
|
|
|
|
DNS is handled automatically by external-dns reading the Ingress
|
|
annotations that kforge writes — no separate DNS step needed.
|
|
|
|
Re-run whenever you add environments or change deploy options.
|
|
|
|
Examples:
|
|
kforge gitea-actions
|
|
kforge gitea-actions --output .gitea/workflows/deploy.yml
|
|
kforge gitea-actions --env staging --env production`,
|
|
RunE: runGiteaActions,
|
|
}
|
|
|
|
func init() {
|
|
giteaActionsCmd.Flags().StringVarP(&giteaActionsOutput, "output", "o",
|
|
".gitea/workflows/deploy.yml",
|
|
"Output path for the generated workflow file")
|
|
giteaActionsCmd.Flags().StringVar(&giteaActionsBranch, "branch", "main",
|
|
"Branch that triggers the workflow")
|
|
giteaActionsCmd.Flags().StringArrayVarP(&giteaActionsEnvs, "env", "e", nil,
|
|
"Environments to deploy (default: all, staging before production)")
|
|
rootCmd.AddCommand(giteaActionsCmd)
|
|
}
|
|
|
|
func runGiteaActions(cmd *cobra.Command, args []string) error {
|
|
cfg, err := loadConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
workflow, err := generator.GenerateGiteaActions(cfg, generator.GiteaActionsOptions{
|
|
Branch: giteaActionsBranch,
|
|
Environments: giteaActionsEnvs,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("generating workflow: %w", err)
|
|
}
|
|
|
|
return writeWorkflow(giteaActionsOutput, workflow)
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// kforge gitea-preview
|
|
// ------------------------------------------------------------
|
|
|
|
var giteaPreviewOutput string
|
|
|
|
var giteaPreviewCmd = &cobra.Command{
|
|
Use: "gitea-preview",
|
|
Short: "Generate a Gitea Actions workflow for PR preview environments",
|
|
Long: `Generates .gitea/workflows/preview.yml that:
|
|
- On PR open/sync: builds a PR-tagged image, applies secrets,
|
|
generates manifests (including a Namespace), and deploys.
|
|
- On PR close: deletes the preview namespace and all resources.
|
|
|
|
Requires preview.enabled: true in kforge.yml.
|
|
|
|
Example kforge.yml preview block:
|
|
preview:
|
|
enabled: true
|
|
base_environment: staging
|
|
namespace_prefix: preview-pr
|
|
hostname_template: "pr-${PR_NUMBER}.${name}.example.com"
|
|
|
|
Examples:
|
|
kforge gitea-preview
|
|
kforge gitea-preview --output .gitea/workflows/preview.yml`,
|
|
RunE: runGiteaPreview,
|
|
}
|
|
|
|
func init() {
|
|
giteaPreviewCmd.Flags().StringVarP(&giteaPreviewOutput, "output", "o",
|
|
".gitea/workflows/preview.yml",
|
|
"Output path for the generated preview workflow file")
|
|
rootCmd.AddCommand(giteaPreviewCmd)
|
|
}
|
|
|
|
func runGiteaPreview(cmd *cobra.Command, args []string) error {
|
|
cfg, err := loadConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
workflow, err := generator.GeneratePreviewActions(cfg)
|
|
if err != nil {
|
|
return fmt.Errorf("generating preview workflow: %w", err)
|
|
}
|
|
|
|
return writeWorkflow(giteaPreviewOutput, workflow)
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Shared helpers
|
|
// ------------------------------------------------------------
|
|
|
|
func writeWorkflow(path, content string) error {
|
|
if path == "-" {
|
|
fmt.Print(content)
|
|
return nil
|
|
}
|
|
|
|
// Ensure parent directory exists.
|
|
dir := path
|
|
for i := len(dir) - 1; i >= 0; i-- {
|
|
if dir[i] == '/' || dir[i] == '\\' {
|
|
dir = dir[:i]
|
|
break
|
|
}
|
|
}
|
|
if dir != path {
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
|
return fmt.Errorf("creating output directory: %w", err)
|
|
}
|
|
}
|
|
|
|
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
|
return fmt.Errorf("writing workflow: %w", err)
|
|
}
|
|
|
|
fmt.Printf("✓ Workflow written to %s\n", path)
|
|
return nil
|
|
}
|