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  }