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