github.com/google/go-github/v66@v66.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 60 // startMigration represents the body of a StartMigration request. 61 type startMigration struct { 62 // Repositories is a slice of repository names to migrate. 63 Repositories []string `json:"repositories,omitempty"` 64 65 // LockRepositories indicates whether repositories should be locked (to prevent 66 // manipulation) while migrating data. 67 LockRepositories *bool `json:"lock_repositories,omitempty"` 68 69 // ExcludeAttachments indicates whether attachments should be excluded from 70 // the migration (to reduce migration archive file size). 71 ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` 72 } 73 74 // StartMigration starts the generation of a migration archive. 75 // repos is a slice of repository names to migrate. 76 // 77 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#start-an-organization-migration 78 // 79 //meta:operation POST /orgs/{org}/migrations 80 func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opts *MigrationOptions) (*Migration, *Response, error) { 81 u := fmt.Sprintf("orgs/%v/migrations", org) 82 83 body := &startMigration{Repositories: repos} 84 if opts != nil { 85 body.LockRepositories = Bool(opts.LockRepositories) 86 body.ExcludeAttachments = Bool(opts.ExcludeAttachments) 87 } 88 89 req, err := s.client.NewRequest("POST", u, body) 90 if err != nil { 91 return nil, nil, err 92 } 93 94 // TODO: remove custom Accept header when this API fully launches. 95 req.Header.Set("Accept", mediaTypeMigrationsPreview) 96 97 m := &Migration{} 98 resp, err := s.client.Do(ctx, req, m) 99 if err != nil { 100 return nil, resp, err 101 } 102 103 return m, resp, nil 104 } 105 106 // ListMigrations lists the most recent migrations. 107 // 108 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#list-organization-migrations 109 // 110 //meta:operation GET /orgs/{org}/migrations 111 func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) { 112 u := fmt.Sprintf("orgs/%v/migrations", org) 113 u, err := addOptions(u, opts) 114 if err != nil { 115 return nil, nil, err 116 } 117 118 req, err := s.client.NewRequest("GET", u, nil) 119 if err != nil { 120 return nil, nil, err 121 } 122 123 // TODO: remove custom Accept header when this API fully launches. 124 req.Header.Set("Accept", mediaTypeMigrationsPreview) 125 126 var m []*Migration 127 resp, err := s.client.Do(ctx, req, &m) 128 if err != nil { 129 return nil, resp, err 130 } 131 132 return m, resp, nil 133 } 134 135 // MigrationStatus gets the status of a specific migration archive. 136 // id is the migration ID. 137 // 138 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#get-an-organization-migration-status 139 // 140 //meta:operation GET /orgs/{org}/migrations/{migration_id} 141 func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { 142 u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) 143 144 req, err := s.client.NewRequest("GET", u, nil) 145 if err != nil { 146 return nil, nil, err 147 } 148 149 // TODO: remove custom Accept header when this API fully launches. 150 req.Header.Set("Accept", mediaTypeMigrationsPreview) 151 152 m := &Migration{} 153 resp, err := s.client.Do(ctx, req, m) 154 if err != nil { 155 return nil, resp, err 156 } 157 158 return m, resp, nil 159 } 160 161 // MigrationArchiveURL fetches a migration archive URL. 162 // id is the migration ID. 163 // 164 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#download-an-organization-migration-archive 165 // 166 //meta:operation GET /orgs/{org}/migrations/{migration_id}/archive 167 func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) { 168 u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) 169 170 req, err := s.client.NewRequest("GET", u, nil) 171 if err != nil { 172 return "", err 173 } 174 175 // TODO: remove custom Accept header when this API fully launches. 176 req.Header.Set("Accept", mediaTypeMigrationsPreview) 177 178 s.client.clientMu.Lock() 179 defer s.client.clientMu.Unlock() 180 181 // Disable the redirect mechanism because AWS fails if the GitHub auth token is provided. 182 var loc string 183 saveRedirect := s.client.client.CheckRedirect 184 s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { 185 loc = req.URL.String() 186 return errors.New("disable redirect") 187 } 188 defer func() { s.client.client.CheckRedirect = saveRedirect }() 189 190 _, err = s.client.Do(ctx, req, nil) // expect error from disable redirect 191 if err == nil { 192 return "", errors.New("expected redirect, none provided") 193 } 194 if !strings.Contains(err.Error(), "disable redirect") { 195 return "", err 196 } 197 return loc, nil 198 } 199 200 // DeleteMigration deletes a previous migration archive. 201 // id is the migration ID. 202 // 203 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#delete-an-organization-migration-archive 204 // 205 //meta:operation DELETE /orgs/{org}/migrations/{migration_id}/archive 206 func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { 207 u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) 208 209 req, err := s.client.NewRequest("DELETE", u, nil) 210 if err != nil { 211 return nil, err 212 } 213 214 // TODO: remove custom Accept header when this API fully launches. 215 req.Header.Set("Accept", mediaTypeMigrationsPreview) 216 217 return s.client.Do(ctx, req, nil) 218 } 219 220 // UnlockRepo unlocks a repository that was locked for migration. 221 // id is the migration ID. 222 // You should unlock each migrated repository and delete them when the migration 223 // is complete and you no longer need the source data. 224 // 225 // GitHub API docs: https://docs.github.com/rest/migrations/orgs#unlock-an-organization-repository 226 // 227 //meta:operation DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock 228 func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) { 229 u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) 230 231 req, err := s.client.NewRequest("DELETE", u, nil) 232 if err != nil { 233 return nil, err 234 } 235 236 // TODO: remove custom Accept header when this API fully launches. 237 req.Header.Set("Accept", mediaTypeMigrationsPreview) 238 239 return s.client.Do(ctx, req, nil) 240 }