github.com/google/go-github/v74@v74.0.0/github/migrations.go (about) 1 // Copyright 2016 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "errors" 11 "fmt" 12 "net/http" 13 "strings" 14 ) 15 16 // MigrationService provides access to the migration related functions 17 // in the GitHub API. 18 // 19 // GitHub API docs: https://docs.github.com/rest/migration/ 20 type MigrationService service 21 22 // Migration represents a GitHub migration (archival). 23 type Migration struct { 24 ID *int64 `json:"id,omitempty"` 25 GUID *string `json:"guid,omitempty"` 26 // State is the current state of a migration. 27 // Possible values are: 28 // "pending" which means the migration hasn't started yet, 29 // "exporting" which means the migration is in progress, 30 // "exported" which means the migration finished successfully, or 31 // "failed" which means the migration failed. 32 State *string `json:"state,omitempty"` 33 // LockRepositories indicates whether repositories are locked (to prevent 34 // manipulation) while migrating data. 35 LockRepositories *bool `json:"lock_repositories,omitempty"` 36 // ExcludeAttachments indicates whether attachments should be excluded from 37 // the migration (to reduce migration archive file size). 38 ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` 39 URL *string `json:"url,omitempty"` 40 CreatedAt *string `json:"created_at,omitempty"` 41 UpdatedAt *string `json:"updated_at,omitempty"` 42 Repositories []*Repository `json:"repositories,omitempty"` 43 } 44 45 func (m Migration) String() string { 46 return Stringify(m) 47 } 48 49 // MigrationOptions specifies the optional parameters to Migration methods. 50 type MigrationOptions struct { 51 // LockRepositories indicates whether repositories should be locked (to prevent 52 // manipulation) while migrating data. 53 LockRepositories bool 54 55 // ExcludeAttachments indicates whether attachments should be excluded from 56 // the migration (to reduce migration archive file size). 57 ExcludeAttachments bool 58 59 // ExcludeReleases indicates whether releases should be excluded from 60 // the migration (to reduce migration archive file size). 61 ExcludeReleases bool 62 63 // Exclude is a slice of related items to exclude from the response in order 64 // to improve performance of the request. Supported values are: "repositories" 65 Exclude []string 66 } 67 68 // startMigration represents the body of a StartMigration request. 69 type startMigration struct { 70 // Repositories is a slice of repository names to migrate. 71 Repositories []string `json:"repositories,omitempty"` 72 73 // LockRepositories indicates whether repositories should be locked (to prevent 74 // manipulation) while migrating data. 75 LockRepositories *bool `json:"lock_repositories,omitempty"` 76 77 // ExcludeAttachments indicates whether attachments should be excluded from 78 // the migration (to reduce migration archive file size). 79 ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` 80 81 // ExcludeReleases indicates whether releases should be excluded from 82 // the migration (to reduce migration archive file size). 83 ExcludeReleases *bool `json:"exclude_releases,omitempty"` 84 85 // Exclude is a slice of related items to exclude from the response in order 86 // to improve performance of the request. Supported values are: "repositories" 87 Exclude []string `json:"exclude,omitempty"` 88 } 89 90 // StartMigration starts the generation of a migration archive. 91 // repos is a slice of repository names to migrate. 92 // 93 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#start-an-organization-migration 94 // 95 //meta:operation POST /orgs/{org}/migrations 96 func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opts *MigrationOptions) (*Migration, *Response, error) { 97 u := fmt.Sprintf("orgs/%v/migrations", org) 98 99 body := &startMigration{Repositories: repos} 100 if opts != nil { 101 body.LockRepositories = Ptr(opts.LockRepositories) 102 body.ExcludeAttachments = Ptr(opts.ExcludeAttachments) 103 body.ExcludeReleases = Ptr(opts.ExcludeReleases) 104 body.Exclude = append(body.Exclude, opts.Exclude...) 105 } 106 107 req, err := s.client.NewRequest("POST", u, body) 108 if err != nil { 109 return nil, nil, err 110 } 111 112 // TODO: remove custom Accept header when this API fully launches. 113 req.Header.Set("Accept", mediaTypeMigrationsPreview) 114 115 m := &Migration{} 116 resp, err := s.client.Do(ctx, req, m) 117 if err != nil { 118 return nil, resp, err 119 } 120 121 return m, resp, nil 122 } 123 124 // ListMigrations lists the most recent migrations. 125 // 126 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#list-organization-migrations 127 // 128 //meta:operation GET /orgs/{org}/migrations 129 func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) { 130 u := fmt.Sprintf("orgs/%v/migrations", org) 131 u, err := addOptions(u, opts) 132 if err != nil { 133 return nil, nil, err 134 } 135 136 req, err := s.client.NewRequest("GET", u, nil) 137 if err != nil { 138 return nil, nil, err 139 } 140 141 // TODO: remove custom Accept header when this API fully launches. 142 req.Header.Set("Accept", mediaTypeMigrationsPreview) 143 144 var m []*Migration 145 resp, err := s.client.Do(ctx, req, &m) 146 if err != nil { 147 return nil, resp, err 148 } 149 150 return m, resp, nil 151 } 152 153 // MigrationStatus gets the status of a specific migration archive. 154 // id is the migration ID. 155 // 156 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#get-an-organization-migration-status 157 // 158 //meta:operation GET /orgs/{org}/migrations/{migration_id} 159 func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { 160 u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) 161 162 req, err := s.client.NewRequest("GET", u, nil) 163 if err != nil { 164 return nil, nil, err 165 } 166 167 // TODO: remove custom Accept header when this API fully launches. 168 req.Header.Set("Accept", mediaTypeMigrationsPreview) 169 170 m := &Migration{} 171 resp, err := s.client.Do(ctx, req, m) 172 if err != nil { 173 return nil, resp, err 174 } 175 176 return m, resp, nil 177 } 178 179 // MigrationArchiveURL fetches a migration archive URL. 180 // id is the migration ID. 181 // 182 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#download-an-organization-migration-archive 183 // 184 //meta:operation GET /orgs/{org}/migrations/{migration_id}/archive 185 func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) { 186 u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) 187 188 req, err := s.client.NewRequest("GET", u, nil) 189 if err != nil { 190 return "", err 191 } 192 193 // TODO: remove custom Accept header when this API fully launches. 194 req.Header.Set("Accept", mediaTypeMigrationsPreview) 195 196 s.client.clientMu.Lock() 197 defer s.client.clientMu.Unlock() 198 199 // Disable the redirect mechanism because AWS fails if the GitHub auth token is provided. 200 var loc string 201 saveRedirect := s.client.client.CheckRedirect 202 s.client.client.CheckRedirect = func(req *http.Request, _ []*http.Request) error { 203 loc = req.URL.String() 204 return errors.New("disable redirect") 205 } 206 defer func() { s.client.client.CheckRedirect = saveRedirect }() 207 208 _, err = s.client.Do(ctx, req, nil) // expect error from disable redirect 209 if err == nil { 210 return "", errors.New("expected redirect, none provided") 211 } 212 if !strings.Contains(err.Error(), "disable redirect") { 213 return "", err 214 } 215 return loc, nil 216 } 217 218 // DeleteMigration deletes a previous migration archive. 219 // id is the migration ID. 220 // 221 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#delete-an-organization-migration-archive 222 // 223 //meta:operation DELETE /orgs/{org}/migrations/{migration_id}/archive 224 func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { 225 u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) 226 227 req, err := s.client.NewRequest("DELETE", u, nil) 228 if err != nil { 229 return nil, err 230 } 231 232 // TODO: remove custom Accept header when this API fully launches. 233 req.Header.Set("Accept", mediaTypeMigrationsPreview) 234 235 return s.client.Do(ctx, req, nil) 236 } 237 238 // UnlockRepo unlocks a repository that was locked for migration. 239 // id is the migration ID. 240 // You should unlock each migrated repository and delete them when the migration 241 // is complete and you no longer need the source data. 242 // 243 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#unlock-an-organization-repository 244 // 245 //meta:operation DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock 246 func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) { 247 u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) 248 249 req, err := s.client.NewRequest("DELETE", u, nil) 250 if err != nil { 251 return nil, err 252 } 253 254 // TODO: remove custom Accept header when this API fully launches. 255 req.Header.Set("Accept", mediaTypeMigrationsPreview) 256 257 return s.client.Do(ctx, req, nil) 258 }