-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpublish.go
More file actions
183 lines (150 loc) · 5.74 KB
/
publish.go
File metadata and controls
183 lines (150 loc) · 5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Package cmd contains all CLI commands for spec-forge.
package cmd
import (
"fmt"
"os"
"github.com/getkin/kin-openapi/openapi3"
"github.com/spf13/cobra"
"github.com/spencercjh/spec-forge/internal/cli"
"github.com/spencercjh/spec-forge/internal/publisher"
)
// publishCmd represents the publish command
var publishCmd = &cobra.Command{
Use: "publish [spec-file]",
Short: "Publish OpenAPI spec to target platform",
Long: `Publish OpenAPI specification to external platforms.
Supports:
- ReadMe (via rdme CLI)
Note: Local file output is handled by the generate command.`,
Args: cobra.MaximumNArgs(1),
RunE: runPublish,
}
func runPublish(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
specFile := "openapi.yaml"
if len(args) > 0 {
specFile = args[0]
}
// Get flag values from command (isolated per command instance)
//nolint:errcheck // flags are bound at command creation, errors not possible
format, _ := cmd.Flags().GetString("format")
//nolint:errcheck
output, _ := cmd.Flags().GetString("output")
//nolint:errcheck
target, _ := cmd.Flags().GetString("to")
//nolint:errcheck
overwrite, _ := cmd.Flags().GetBool("overwrite")
//nolint:errcheck
readMeAPIKey, _ := cmd.Flags().GetString("readme-api-key")
//nolint:errcheck
readMeBranch, _ := cmd.Flags().GetString("readme-branch")
//nolint:errcheck
readMeSlug, _ := cmd.Flags().GetString("readme-slug")
//nolint:errcheck
readMeUseSpecVersion, _ := cmd.Flags().GetBool("readme-use-spec-version")
cli.Statusf(os.Stderr, "Publishing spec to %s", target)
// Create publisher using factory
pub, err := publisher.NewPublisher(target)
if err != nil {
return fmt.Errorf("failed to create publisher: %w", err)
}
cli.Statusf(os.Stderr, "Using publisher: %s", pub.Name())
// Load spec file
specData, err := os.ReadFile(specFile)
if err != nil {
return fmt.Errorf("failed to read spec file: %w", err)
}
spec, err := openapi3.NewLoader().LoadFromData(specData)
if err != nil {
return fmt.Errorf("failed to parse spec: %w", err)
}
// Build publish options
opts := &publisher.PublishOptions{
OutputPath: output,
Format: format,
Overwrite: overwrite,
}
// Add ReadMe-specific options if using ReadMe publisher
if pub.Name() == "readme" {
// Resolve API key from flag or environment variable
apiKey := readMeAPIKey
if apiKey == "" {
apiKey = os.Getenv("README_API_KEY")
}
opts.ReadMe = &publisher.ReadMeOptions{
APIKey: apiKey,
Branch: readMeBranch,
Slug: readMeSlug,
UseSpecVersion: readMeUseSpecVersion,
}
}
// Publish
result, err := pub.Publish(ctx, spec, opts)
if err != nil {
return fmt.Errorf("failed to publish: %w", err)
}
cli.Successf(os.Stderr, "Published successfully (%d bytes, %s)", result.BytesWritten, result.Format)
if result.Message != "" {
cli.Statusf(os.Stderr, "%s", result.Message)
}
return nil
}
// newPublishCmd creates a new publish command instance for testing.
func newPublishCmd() *cobra.Command {
c := &cobra.Command{
Use: "publish [spec-file]",
Short: "Publish OpenAPI spec to target platform",
Long: `Publish OpenAPI specification to external platforms.
Supports:
- ReadMe (via rdme CLI)
Note: Local file output is handled by the generate command.`,
Args: cobra.MaximumNArgs(1),
RunE: runPublish,
}
c.Flags().StringP("format", "f", "yaml", "output format (yaml or json)")
c.Flags().StringP("output", "o", "", "output file path (currently unused for 'readme'; reserved for future publishers)")
c.Flags().StringP("to", "t", "", "publish target (required: readme)")
c.Flags().Bool("overwrite", false, "overwrite existing spec")
// ReadMe-specific flags
c.Flags().String("readme-api-key", "", "ReadMe API key (or set README_API_KEY env var)")
c.Flags().String("readme-branch", "", "ReadMe version/branch (default: stable)")
c.Flags().String("readme-slug", "", "ReadMe API slug/identifier")
c.Flags().Bool("readme-use-spec-version", false, "use OpenAPI info.version as ReadMe version")
// Mark target as required
if err := c.MarkFlagRequired("to"); err != nil {
panic(fmt.Sprintf("failed to mark flag 'to' as required: %v", err))
}
registerCompletion(c, "format", []string{"yaml", "json"})
registerCompletion(c, "to", []string{"readme"})
return c
}
// publish command flag variables for global rootCmd only
var (
publishFormat string
publishOutput string
publishTarget string
publishOverwrite bool
// ReadMe-specific flags
readMeAPIKey string
readMeBranch string
readMeSlug string
readMeUseSpecVersion bool
)
func init() {
rootCmd.AddCommand(publishCmd)
publishCmd.Flags().StringVarP(&publishFormat, "format", "f", "yaml", "output format (yaml or json)")
publishCmd.Flags().StringVarP(&publishOutput, "output", "o", "", "output file path (currently unused for 'readme'; reserved for future publishers)")
publishCmd.Flags().StringVarP(&publishTarget, "to", "t", "", "publish target (required: readme)")
publishCmd.Flags().BoolVar(&publishOverwrite, "overwrite", false, "overwrite existing spec")
// ReadMe-specific flags
publishCmd.Flags().StringVar(&readMeAPIKey, "readme-api-key", "", "ReadMe API key (or set README_API_KEY env var)")
publishCmd.Flags().StringVar(&readMeBranch, "readme-branch", "", "ReadMe version/branch (default: stable)")
publishCmd.Flags().StringVar(&readMeSlug, "readme-slug", "", "ReadMe API slug/identifier")
publishCmd.Flags().BoolVar(&readMeUseSpecVersion, "readme-use-spec-version", false, "use OpenAPI info.version as ReadMe version")
// Mark target as required
if err := publishCmd.MarkFlagRequired("to"); err != nil {
panic(fmt.Sprintf("failed to mark flag 'to' as required: %v", err))
}
registerCompletion(publishCmd, "format", []string{"yaml", "json"})
registerCompletion(publishCmd, "to", []string{"readme"})
}