[Feature] Create repository from template
Co-authored-by: Mislav Marohnić <mislav@github.com>
This commit is contained in:
parent
727b726667
commit
58f62a4a15
3 changed files with 110 additions and 6 deletions
|
|
@ -14,3 +14,14 @@ func CurrentLoginName(client *Client, hostname string) (string, error) {
|
|||
err := gql.QueryNamed(context.Background(), "UserCurrent", &query, nil)
|
||||
return query.Viewer.Login, err
|
||||
}
|
||||
|
||||
func CurrentUserID(client *Client, hostname string) (string, error) {
|
||||
var query struct {
|
||||
Viewer struct {
|
||||
ID string
|
||||
}
|
||||
}
|
||||
gql := graphQLClient(client.http, hostname)
|
||||
err := gql.QueryNamed(context.Background(), "UserCurrent", &query, nil)
|
||||
return query.Viewer.ID, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import (
|
|||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/MakeNowJust/heredoc"
|
||||
"github.com/cli/cli/api"
|
||||
"github.com/cli/cli/git"
|
||||
"github.com/cli/cli/internal/config"
|
||||
"github.com/cli/cli/internal/ghinstance"
|
||||
"github.com/cli/cli/internal/ghrepo"
|
||||
"github.com/cli/cli/internal/run"
|
||||
"github.com/cli/cli/pkg/cmdutil"
|
||||
|
|
@ -28,6 +30,7 @@ type CreateOptions struct {
|
|||
Description string
|
||||
Homepage string
|
||||
Team string
|
||||
Template string
|
||||
EnableIssues bool
|
||||
EnableWiki bool
|
||||
Public bool
|
||||
|
|
@ -80,6 +83,7 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
|
|||
cmd.Flags().StringVarP(&opts.Description, "description", "d", "", "Description of repository")
|
||||
cmd.Flags().StringVarP(&opts.Homepage, "homepage", "h", "", "Repository home page URL")
|
||||
cmd.Flags().StringVarP(&opts.Team, "team", "t", "", "The name of the organization team to be granted access")
|
||||
cmd.Flags().StringVarP(&opts.Template, "template", "p", "", "Make the new repository based on a template repository")
|
||||
cmd.Flags().BoolVar(&opts.EnableIssues, "enable-issues", true, "Enable issues in the new repository")
|
||||
cmd.Flags().BoolVar(&opts.EnableWiki, "enable-wiki", true, "Enable wiki in the new repository")
|
||||
cmd.Flags().BoolVar(&opts.Public, "public", false, "Make the new repository public")
|
||||
|
|
@ -164,11 +168,45 @@ func createRun(opts *CreateOptions) error {
|
|||
}
|
||||
}
|
||||
|
||||
// find template ID
|
||||
|
||||
if opts.Template != "" {
|
||||
httpClient, err := opts.HttpClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var toView ghrepo.Interface
|
||||
apiClient := api.NewClientFromHTTP(httpClient)
|
||||
|
||||
// var err errors
|
||||
viewURL := opts.Template
|
||||
if !strings.Contains(viewURL, "/") {
|
||||
currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
viewURL = currentUser + "/" + viewURL
|
||||
}
|
||||
toView, err = ghrepo.FromFullName(viewURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("argument error: %w", err)
|
||||
}
|
||||
|
||||
repo, err := api.GitHubRepo(apiClient, toView)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts.Template = repo.ID
|
||||
}
|
||||
|
||||
input := repoCreateInput{
|
||||
Name: repoToCreate.RepoName(),
|
||||
Visibility: visibility,
|
||||
OwnerID: repoToCreate.RepoOwner(),
|
||||
TeamID: opts.Team,
|
||||
RepositoryID: opts.Template,
|
||||
Description: opts.Description,
|
||||
HomepageURL: opts.Homepage,
|
||||
HasIssuesEnabled: opts.EnableIssues,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ type repoCreateInput struct {
|
|||
HomepageURL string `json:"homepageUrl,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
RepositoryID string `json:"repositoryId,omitempty"`
|
||||
|
||||
OwnerID string `json:"ownerId,omitempty"`
|
||||
TeamID string `json:"teamId,omitempty"`
|
||||
|
||||
|
|
@ -21,16 +23,18 @@ type repoCreateInput struct {
|
|||
HasWikiEnabled bool `json:"hasWikiEnabled"`
|
||||
}
|
||||
|
||||
type repoTemplateInput struct {
|
||||
Name string `json:"name"`
|
||||
Visibility string `json:"visibility"`
|
||||
OwnerID string `json:"ownerId,omitempty"`
|
||||
|
||||
RepositoryID string `json:"repositoryId,omitempty"`
|
||||
}
|
||||
|
||||
// repoCreate creates a new GitHub repository
|
||||
func repoCreate(client *http.Client, hostname string, input repoCreateInput) (*api.Repository, error) {
|
||||
apiClient := api.NewClientFromHTTP(client)
|
||||
|
||||
var response struct {
|
||||
CreateRepository struct {
|
||||
Repository api.Repository
|
||||
}
|
||||
}
|
||||
|
||||
if input.TeamID != "" {
|
||||
orgID, teamID, err := resolveOrganizationTeam(apiClient, hostname, input.OwnerID, input.TeamID)
|
||||
if err != nil {
|
||||
|
|
@ -46,6 +50,57 @@ func repoCreate(client *http.Client, hostname string, input repoCreateInput) (*a
|
|||
input.OwnerID = orgID
|
||||
}
|
||||
|
||||
if input.RepositoryID != "" {
|
||||
var response struct {
|
||||
CloneTemplateRepository struct {
|
||||
Repository api.Repository
|
||||
}
|
||||
}
|
||||
|
||||
if input.OwnerID == "" {
|
||||
var err error
|
||||
input.OwnerID, err = api.CurrentUserID(apiClient, hostname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
templateInput := repoTemplateInput{
|
||||
Name: input.Name,
|
||||
Visibility: input.Visibility,
|
||||
OwnerID: input.OwnerID,
|
||||
RepositoryID: input.RepositoryID,
|
||||
}
|
||||
|
||||
variables := map[string]interface{}{
|
||||
"input": templateInput,
|
||||
}
|
||||
|
||||
err := apiClient.GraphQL(hostname, `
|
||||
mutation CloneTemplateRepository($input: CloneTemplateRepositoryInput!) {
|
||||
cloneTemplateRepository(input: $input) {
|
||||
repository {
|
||||
id
|
||||
name
|
||||
owner { login }
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
`, variables, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return api.InitRepoHostname(&response.CloneTemplateRepository.Repository, hostname), nil
|
||||
}
|
||||
|
||||
var response struct {
|
||||
CreateRepository struct {
|
||||
Repository api.Repository
|
||||
}
|
||||
}
|
||||
|
||||
variables := map[string]interface{}{
|
||||
"input": input,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue