package cmd import ( "context" "encoding/json" "errors" "time" "github.com/Pingu-Studio/MaidnCLI/internal/e2e" "github.com/spf13/cobra" ) var ( e2eKubeconfig, e2eContext, e2eExternalSecret, e2ePipelineRun string e2ePreviewURL, e2ePreviewSentinel string e2ePromotionPullsURL, e2ePromotionOwner, e2ePromotionHead string e2ePromotionTokenEnv, e2ePromotionTokenFile string e2eFluxKustomizations []string e2eTimeout, e2eInterval time.Duration e2eRunner = e2e.DefaultRunner errE2EChecks = errors.New("e2e checks failed") ) var e2eCmd = &cobra.Command{ Use: "e2e", Short: "Run bounded, read-only delivery checks and emit JSON.", RunE: runE2E, } func init() { rootCmd.AddCommand(e2eCmd) e2eCmd.Flags().StringVar(&e2eKubeconfig, "kubeconfig", "", "Path to a read-only kubeconfig") e2eCmd.Flags().StringVar(&e2eContext, "context", "", "Kubernetes context name") e2eCmd.Flags().StringSliceVar(&e2eFluxKustomizations, "flux-kustomization", nil, "Flux Kustomization namespace/name (repeatable)") e2eCmd.Flags().StringVar(&e2eExternalSecret, "external-secret", "", "ExternalSecret namespace/name") e2eCmd.Flags().StringVar(&e2ePipelineRun, "pipelinerun", "", "PipelineRun namespace/name") e2eCmd.Flags().StringVar(&e2ePreviewURL, "preview-url", "", "Credential-free preview HTTP(S) URL") e2eCmd.Flags().StringVar(&e2ePreviewSentinel, "preview-sentinel", "", "Non-secret text expected in the preview response") e2eCmd.Flags().StringVar(&e2ePromotionPullsURL, "promotion-pulls-url", "", "Credential-free Forgejo pulls API URL without query parameters") e2eCmd.Flags().StringVar(&e2ePromotionOwner, "promotion-owner", "", "Forgejo owner for the promotion branch") e2eCmd.Flags().StringVar(&e2ePromotionHead, "promotion-head", "", "Expected promotion branch name") e2eCmd.Flags().StringVar(&e2ePromotionTokenEnv, "promotion-token-env", "", "Environment variable containing the Forgejo token") e2eCmd.Flags().StringVar(&e2ePromotionTokenFile, "promotion-token-file", "", "Path to a file containing the Forgejo token") e2eCmd.Flags().DurationVar(&e2eTimeout, "timeout", 2*time.Minute, "Maximum wait for each check (up to 10m)") e2eCmd.Flags().DurationVar(&e2eInterval, "interval", 2*time.Second, "Polling interval") for _, name := range []string{"kubeconfig", "flux-kustomization", "external-secret", "pipelinerun", "preview-url", "preview-sentinel", "promotion-pulls-url", "promotion-owner", "promotion-head"} { _ = e2eCmd.MarkFlagRequired(name) } } func runE2E(cmd *cobra.Command, _ []string) error { token, err := e2e.ReadToken(e2ePromotionTokenEnv, e2ePromotionTokenFile) if err != nil { return err } ctx := cmd.Context() if ctx == nil { ctx = context.Background() } result, err := e2eRunner().Run(ctx, e2e.Options{ Kubeconfig: e2eKubeconfig, Context: e2eContext, FluxKustomizations: e2eFluxKustomizations, ExternalSecret: e2eExternalSecret, PipelineRun: e2ePipelineRun, PreviewURL: e2ePreviewURL, PreviewSentinel: e2ePreviewSentinel, PromotionPullsURL: e2ePromotionPullsURL, PromotionOwner: e2ePromotionOwner, PromotionHead: e2ePromotionHead, PromotionToken: token, Timeout: e2eTimeout, Interval: e2eInterval, }) if err != nil { return err } if err := json.NewEncoder(cmd.OutOrStdout()).Encode(result); err != nil { return err } if !result.Passed { return errE2EChecks } return nil }