99 "net/http"
1010 "os"
1111 "path/filepath"
12+ "slices"
1213 "strings"
1314 "time"
1415
@@ -18,15 +19,15 @@ import (
1819 "github.com/buildkite/cli/v3/pkg/cmd/factory"
1920)
2021
21- var MigrationEndpoint = "https://m4vrh5pvtd.execute-api.us-east-1.amazonaws.com/production/migrate"
22+ var convertEndpoint = "https://m4vrh5pvtd.execute-api.us-east-1.amazonaws.com/production/migrate"
2223
23- type migrationRequest struct {
24+ type conversionRequest struct {
2425 Vendor string `json:"vendor"`
2526 Code string `json:"code"`
2627 AI bool `json:"ai,omitempty"`
2728}
2829
29- type migrationResponse struct {
30+ type conversionResponse struct {
3031 JobID string `json:"jobId"`
3132 Status string `json:"status"`
3233 Message string `json:"message"`
@@ -43,16 +44,16 @@ type statusResponse struct {
4344 Error string `json:"error,omitempty"`
4445}
4546
46- type MigrateCmd struct {
47- File string `help:"Path to the pipeline file to migrate (required)" short:"F" required:""`
47+ type ConvertCmd struct {
48+ File string `help:"Path to the pipeline file to convert (required)" short:"F" required:""`
4849 Vendor string `help:"CI/CD vendor (auto-detected if not specified)" short:"v"`
49- AI bool `help:"Use AI-powered migration (recommended for Jenkins)"`
50- Output string `help:"Custom path to save the migrated pipeline (default: .buildkite/pipeline.<vendor>.yml)" short:"o"`
51- Timeout int `help:"Timeout in seconds (use 600+ for AI migrations )" default:"300"`
50+ AI bool `help:"Use AI-powered conversion (recommended for Jenkins)"`
51+ Output string `help:"Custom path to save the converted pipeline (default: .buildkite/pipeline.<vendor>.yml)" short:"o"`
52+ Timeout int `help:"Timeout in seconds (use 600+ for AI conversions )" default:"300"`
5253}
5354
54- func (c * MigrateCmd ) Help () string {
55- return `Migrate a CI/CD pipeline configuration from various vendors to Buildkite format.
55+ func (c * ConvertCmd ) Help () string {
56+ return `Convert a CI/CD pipeline configuration from various vendors to Buildkite format.
5657
5758Supported vendors:
5859 - github (GitHub Actions)
@@ -62,27 +63,27 @@ Supported vendors:
6263
6364The command will automatically detect the vendor based on the file name if not specified.
6465
65- By default, the migrated pipeline is saved to .buildkite/pipeline.<vendor>.yml.
66+ By default, the converted pipeline is saved to .buildkite/pipeline.<vendor>.yml.
6667Use the --output flag to specify a custom output path.
6768
68- Note: This command does not require an API token since it uses a public migration API.
69+ Note: This command does not require an API token since it uses a public conversion API.
6970
7071Examples:
71- # Migrate a GitHub Actions workflow
72- $ bk pipeline migrate -F .github/workflows/ci.yml
72+ # Convert a GitHub Actions workflow
73+ $ bk pipeline convert -F .github/workflows/ci.yml
7374
74- # Migrate with explicit vendor specification
75- $ bk pipeline migrate -F pipeline.yml --vendor circleci
75+ # Convert with explicit vendor specification
76+ $ bk pipeline convert -F pipeline.yml --vendor circleci
7677
77- # Migrate Jenkins pipeline with AI support
78- $ bk pipeline migrate -F Jenkinsfile --ai
78+ # Convert Jenkins pipeline with AI support
79+ $ bk pipeline convert -F Jenkinsfile --ai
7980
8081 # Save output to a file
81- $ bk pipeline migrate -F .github/workflows/ci.yml -o .buildkite/pipeline.yml
82+ $ bk pipeline convert -F .github/workflows/ci.yml -o .buildkite/pipeline.yml
8283`
8384}
8485
85- func (c * MigrateCmd ) Run (kongCtx * kong.Context , globals cli.GlobalFlags ) error {
86+ func (c * ConvertCmd ) Run (kongCtx * kong.Context , globals cli.GlobalFlags ) error {
8687 f , err := factory .New (factory .WithDebug (globals .EnableDebug ()))
8788 if err != nil {
8889 return err
@@ -106,46 +107,46 @@ func (c *MigrateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
106107 }
107108
108109 supportedVendors := []string {"github" , "bitbucket" , "circleci" , "jenkins" }
109- if ! contains (supportedVendors , c .Vendor ) {
110+ if ! slices . Contains (supportedVendors , c .Vendor ) {
110111 return fmt .Errorf ("unsupported vendor: %s (supported: %s)" , c .Vendor , strings .Join (supportedVendors , ", " ))
111112 }
112113
113- req := migrationRequest {
114+ req := conversionRequest {
114115 Vendor : c .Vendor ,
115116 Code : string (content ),
116117 AI : c .AI ,
117118 }
118119
119- fmt .Println ("Submitting migration job..." )
120+ fmt .Println ("Submitting conversion job..." )
120121
121- jobResp , err := submitMigrationJob (req )
122+ jobResp , err := submitConversionJob (req )
122123 if err != nil {
123- return fmt .Errorf ("error submitting migration job: %w" , err )
124+ return fmt .Errorf ("error submitting conversion job: %w" , err )
124125 }
125126
126127 if c .AI {
127128 fmt .Println ("Job submitted. Processing with AI (this may take several minutes)..." )
128129 } else {
129- fmt .Println ("Job submitted. Processing migration ..." )
130+ fmt .Println ("Job submitted. Processing conversion ..." )
130131 }
131132
132133 var result * statusResponse
133- err = bkIO .SpinWhile (f , "Processing migration ..." , func () {
134+ err = bkIO .SpinWhile (f , "Processing conversion ..." , func () {
134135 result , err = pollJobStatus (jobResp .JobID , c .Timeout )
135136 })
136137 if err != nil {
137138 return fmt .Errorf ("error polling job status: %w" , err )
138139 }
139140
140141 if result .Status == "failed" {
141- return fmt .Errorf ("migration failed: %s" , result .Error )
142+ return fmt .Errorf ("conversion failed: %s" , result .Error )
142143 }
143144
144145 if c .Output != "" {
145146 if err := os .WriteFile (c .Output , []byte (result .Result ), 0o644 ); err != nil {
146147 return fmt .Errorf ("error writing output file: %w" , err )
147148 }
148- fmt .Printf ("\n ✅ Migration completed successfully!\n " )
149+ fmt .Printf ("\n ✅ conversion completed successfully!\n " )
149150 fmt .Printf ("Output saved to: %s\n " , c .Output )
150151 } else {
151152 buildkiteDir := ".buildkite"
@@ -160,7 +161,7 @@ func (c *MigrateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
160161 return fmt .Errorf ("error writing output file: %w" , err )
161162 }
162163
163- fmt .Printf ("\n ✅ Migration completed successfully!\n " )
164+ fmt .Printf ("\n ✅ conversion completed successfully!\n " )
164165 fmt .Printf ("Output saved to: %s\n " , defaultOutputPath )
165166 }
166167
@@ -189,22 +190,13 @@ func detectVendor(filePath string) (string, error) {
189190 return "" , fmt .Errorf ("could not detect vendor from file path. Please specify vendor explicitly with --vendor" )
190191}
191192
192- func contains (slice []string , str string ) bool {
193- for _ , s := range slice {
194- if s == str {
195- return true
196- }
197- }
198- return false
199- }
200-
201- func submitMigrationJob (req migrationRequest ) (* migrationResponse , error ) {
193+ func submitConversionJob (req conversionRequest ) (* conversionResponse , error ) {
202194 reqBody , err := json .Marshal (req )
203195 if err != nil {
204196 return nil , fmt .Errorf ("error marshaling request: %w" , err )
205197 }
206198
207- httpReq , err := http .NewRequestWithContext (context .Background (), "POST" , MigrationEndpoint , bytes .NewReader (reqBody ))
199+ httpReq , err := http .NewRequestWithContext (context .Background (), "POST" , convertEndpoint , bytes .NewReader (reqBody ))
208200 if err != nil {
209201 return nil , fmt .Errorf ("error creating request: %w" , err )
210202 }
@@ -227,7 +219,7 @@ func submitMigrationJob(req migrationRequest) (*migrationResponse, error) {
227219 return nil , fmt .Errorf ("API request failed (status %d): %s" , resp .StatusCode , string (body ))
228220 }
229221
230- var jobResp migrationResponse
222+ var jobResp conversionResponse
231223 if err := json .Unmarshal (body , & jobResp ); err != nil {
232224 return nil , fmt .Errorf ("error parsing response: %w" , err )
233225 }
@@ -236,7 +228,7 @@ func submitMigrationJob(req migrationRequest) (*migrationResponse, error) {
236228}
237229
238230func pollJobStatus (jobID string , timeoutSeconds int ) (* statusResponse , error ) {
239- statusURL := fmt .Sprintf ("%s/%s/status" , MigrationEndpoint , jobID )
231+ statusURL := fmt .Sprintf ("%s/%s/status" , convertEndpoint , jobID )
240232 client := & http.Client {Timeout : 30 * time .Second }
241233
242234 maxAttempts := timeoutSeconds / 5
@@ -281,5 +273,5 @@ func pollJobStatus(jobID string, timeoutSeconds int) (*statusResponse, error) {
281273 }
282274 }
283275
284- return nil , fmt .Errorf ("migration timed out after %d seconds" , timeoutSeconds )
276+ return nil , fmt .Errorf ("conversion timed out after %d seconds" , timeoutSeconds )
285277}
0 commit comments