Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/pkg/cli/pipeline_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ func (o *deletePipelineOpts) deleteSecret() error {
if o.PipelineSecret == "" {
return nil
}
// Only pipelines created with GitHubV1 have personal access tokens saved as secrets.
if !o.shouldDeleteSecret {
confirmDeletion, err := o.prompt.Confirm(
fmt.Sprintf(pipelineSecretDeleteConfirmPrompt, o.PipelineSecret, o.PipelineName),
Expand Down
54 changes: 21 additions & 33 deletions internal/pkg/cli/pipeline_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,19 @@ Please enter full repository URL, e.g. "https://github.com/myCompany/myRepo", or

const (
buildspecTemplatePath = "cicd/buildspec.yml"

fmtPipelineName = "pipeline-%s-%s" // Ex: "pipeline-appName-repoName"
// For a GitHub repository.
githubURL = "github.com"
ghProviderName = "GitHub"
defaultGHBranch = "main"
fmtPipelineName = "pipeline-%s-%s" // Ex: "pipeline-appName-repoName"
fmtGHRepoURL = "https://%s/%s/%s" // Ex: "https://github.com/repoOwner/repoName"
fmtSecretName = "github-token-%s-%s" // Ex: "github-token-appName-repoName"
// For a CodeCommit repository.
awsURL = "aws.amazon.com"
ccIdentifier = "codecommit"
ccProviderName = "CodeCommit"
defaultCCBranch = "master"
fmtCCRepoURL = "https://%s.console.%s/codesuite/codecommit/repositories/%s/browse" // Ex: "https://region.console.aws.amazon.com/codesuite/codecommit/repositories/repoName/browse"
// For a Bitbucket repository.
bbURL = "bitbucket.org"
bbProviderName = "Bitbucket"
defaultBBBranch = "master"
fmtBBRepoURL = "https://%s@%s/%s/%s" // Ex: "https://repoOwner@bitbucket.org/repoOwner/repoName
)
Expand Down Expand Up @@ -190,7 +186,7 @@ func (o *initPipelineOpts) Ask() error {

// Execute writes the pipeline manifest file.
func (o *initPipelineOpts) Execute() error {
if o.provider == ghProviderName {
if o.provider == manifest.GithubV1ProviderName {
if err := o.storeGitHubAccessToken(); err != nil {
return err
}
Expand Down Expand Up @@ -270,27 +266,28 @@ func (o *initPipelineOpts) askRepository() error {
}

func (o *initPipelineOpts) askGitHubRepoDetails() error {
o.provider = ghProviderName
// If the user uses a flag to specify a GitHub access token,
// GitHub version 1 (not CSC) is the provider.
o.provider = manifest.GithubProviderName
if o.githubAccessToken != "" {
o.provider = manifest.GithubV1ProviderName
}

repoDetails, err := ghRepoURL(o.repoURL).parse()
if err != nil {
return err
}
o.repoName = repoDetails.name
o.repoOwner = repoDetails.owner

if o.githubAccessToken == "" {
if err = o.getGitHubAccessToken(); err != nil {
return err
}
}
if o.repoBranch == "" {
o.repoBranch = defaultGHBranch
}
return nil
}

func (o *initPipelineOpts) parseCodeCommitRepoDetails() error {
o.provider = ccProviderName
o.provider = manifest.CodeCommitProviderName
repoDetails, err := ccRepoURL(o.repoURL).parse()
if err != nil {
return err
Expand All @@ -315,7 +312,7 @@ func (o *initPipelineOpts) parseCodeCommitRepoDetails() error {
}

func (o *initPipelineOpts) parseBitbucketRepoDetails() error {
o.provider = bbProviderName
o.provider = manifest.BitbucketProviderName
repoDetails, err := bbRepoURL(o.repoURL).parse()
if err != nil {
return err
Expand Down Expand Up @@ -469,20 +466,6 @@ func (url bbRepoURL) parse() (bbRepoDetails, error) {
}, nil
}

func (o *initPipelineOpts) getGitHubAccessToken() error {
Comment thread
huanjani marked this conversation as resolved.
token, err := o.prompt.GetSecret(
fmt.Sprintf("Please enter your GitHub Personal Access Token for your repository %s:", color.HighlightUserInput(o.repoName)),
`The personal access token for the GitHub repository linked to your workspace.
For more information, please refer to: https://git.io/JfDFD.`,
)

if err != nil {
return fmt.Errorf("get GitHub access token: %w", err)
}
o.githubAccessToken = token
return nil
}

func (o *initPipelineOpts) storeGitHubAccessToken() error {
secretName := o.secretName()
_, err := o.secretsmanager.CreateSecret(secretName, o.githubAccessToken)
Expand Down Expand Up @@ -608,18 +591,23 @@ func (o *initPipelineOpts) pipelineName() string {
func (o *initPipelineOpts) pipelineProvider() (manifest.Provider, error) {
var config interface{}
switch o.provider {
case ghProviderName:
config = &manifest.GitHubProperties{
case manifest.GithubV1ProviderName:
config = &manifest.GitHubV1Properties{
RepositoryURL: fmt.Sprintf(fmtGHRepoURL, githubURL, o.repoOwner, o.repoName),
Branch: o.repoBranch,
GithubSecretIdKeyName: o.secret,
}
case ccProviderName:
case manifest.GithubProviderName:
config = &manifest.GitHubProperties{
RepositoryURL: fmt.Sprintf(fmtGHRepoURL, githubURL, o.repoOwner, o.repoName),
Branch: o.repoBranch,
}
case manifest.CodeCommitProviderName:
config = &manifest.CodeCommitProperties{
RepositoryURL: fmt.Sprintf(fmtCCRepoURL, o.ccRegion, awsURL, o.repoName),
Branch: o.repoBranch,
}
case bbProviderName:
case manifest.BitbucketProviderName:
config = &manifest.BitbucketProperties{
RepositoryURL: fmt.Sprintf(fmtBBRepoURL, o.repoOwner, bbURL, o.repoOwner, o.repoName),
Branch: o.repoBranch,
Expand Down Expand Up @@ -669,7 +657,6 @@ func buildPipelineInitCmd() *cobra.Command {
Create a pipeline for the services in your workspace.
/code $ copilot pipeline init \
/code --url https://github.com/gitHubUserName/myFrontendApp.git \
/code --github-access-token file://myGitHubToken \
/code --environments "stage,prod"`,
RunE: runCmdE(func(cmd *cobra.Command, args []string) error {
opts, err := newInitPipelineOpts(vars)
Expand Down Expand Up @@ -698,6 +685,7 @@ func buildPipelineInitCmd() *cobra.Command {
_ = cmd.Flags().MarkHidden(githubURLFlag)
cmd.Flags().StringVarP(&vars.repoURL, repoURLFlag, repoURLFlagShort, "", repoURLFlagDescription)
cmd.Flags().StringVarP(&vars.githubAccessToken, githubAccessTokenFlag, githubAccessTokenFlagShort, "", githubAccessTokenFlagDescription)
_ = cmd.Flags().MarkHidden(githubAccessTokenFlag)
Comment thread
huanjani marked this conversation as resolved.
cmd.Flags().StringVarP(&vars.repoBranch, gitBranchFlag, gitBranchFlagShort, "", gitBranchFlagDescription)
cmd.Flags().StringSliceVarP(&vars.environments, envsFlag, envsFlagShort, []string{}, pipelineEnvsFlagDescription)

Expand Down
114 changes: 56 additions & 58 deletions internal/pkg/cli/pipeline_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,8 @@ func TestInitPipelineOpts_Validate(t *testing.T) {
}

func TestInitPipelineOpts_Ask(t *testing.T) {
githubOwner := "badGoose"
githubRepoName := "chaOS"
githubAnotherOwner := "goodGoose"
githubOwner := "goodGoose"
Comment thread
huanjani marked this conversation as resolved.
githubAnotherRepoName := "bhaOS"
githubURL := "https://github.com/badGoose/chaOS"
githubAnotherURL := "git@github.com:goodGoose/bhaOS.git"
githubReallyBadURL := "reallybadGoosegithub.comNotEvenAURL"
githubToken := "hunter2"
Expand Down Expand Up @@ -181,7 +178,7 @@ func TestInitPipelineOpts_Ask(t *testing.T) {
"no flags, prompts for all input, success case for GitHub": {
inEnvironments: []string{},
inRepoURL: "",
inGitHubAccessToken: "",
inGitHubAccessToken: githubToken,
inGitBranch: "",
buffer: *bytes.NewBufferString("archer\tgit@github.com:goodGoose/bhaOS (fetch)\narcher\thttps://github.com/badGoose/chaOS (push)\narcher\tcodecommit::us-west-2://repo-man (fetch)\n"),

Expand All @@ -203,12 +200,11 @@ func TestInitPipelineOpts_Ask(t *testing.T) {
},
mockPrompt: func(m *mocks.Mockprompter) {
m.EXPECT().SelectOne(pipelineSelectURLPrompt, gomock.Any(), gomock.Any()).Return(githubAnotherURL, nil).Times(1)
m.EXPECT().GetSecret(gomock.Eq("Please enter your GitHub Personal Access Token for your repository bhaOS:"), gomock.Any()).Return(githubToken, nil).Times(1)
},
mockSessProvider: func(m *mocks.MocksessionProvider) {},

expectedRepoURL: githubAnotherURL,
expectedGitHubOwner: githubAnotherOwner,
expectedGitHubOwner: githubOwner,
expectedRepoName: githubAnotherRepoName,
expectedGitHubAccessToken: githubToken,
expectedRepoBranch: "main",
Expand Down Expand Up @@ -364,42 +360,6 @@ func TestInitPipelineOpts_Ask(t *testing.T) {
expectedEnvironments: []string{"test", "prod"},
expectedError: fmt.Errorf("unable to parse the GitHub repository owner and name from reallybadGoosegithub.comNotEvenAURL: please pass the repository URL with the format `--url https://github.com/{owner}/{repositoryName}`"),
},
"returns error if fail to get GitHub access token": {
inEnvironments: []string{},
inRepoURL: "",
inGitHubAccessToken: "",
inGitBranch: "",
buffer: *bytes.NewBufferString("archer\tgit@github.com:goodGoose/bhaOS (fetch)\narcher\thttps://github.com/badGoose/chaOS (push)\n"),

mockSelector: func(m *mocks.MockpipelineSelector) {
m.EXPECT().Environments(pipelineSelectEnvPrompt, gomock.Any(), "my-app", gomock.Any()).Return([]string{"test", "prod"}, nil)
},
mockStore: func(m *mocks.Mockstore) {
m.EXPECT().GetEnvironment("my-app", "test").Return(&config.Environment{
Name: "test",
Region: "us-west-2",
}, nil)
m.EXPECT().GetEnvironment("my-app", "prod").Return(&config.Environment{
Name: "prod",
Region: "us-west-2",
}, nil)
},
mockRunner: func(m *mocks.Mockrunner) {
m.EXPECT().Run(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
},
mockPrompt: func(m *mocks.Mockprompter) {
m.EXPECT().SelectOne(pipelineSelectURLPrompt, gomock.Any(), gomock.Any()).Return(githubURL, nil).Times(1)
m.EXPECT().GetSecret(gomock.Eq("Please enter your GitHub Personal Access Token for your repository chaOS:"), gomock.Any()).Return("", errors.New("some error")).Times(1)
},
mockSessProvider: func(m *mocks.MocksessionProvider) {},

expectedGitHubOwner: githubOwner,
expectedRepoName: githubRepoName,
expectedGitHubAccessToken: "",
expectedRepoBranch: "main",
expectedEnvironments: []string{"test", "prod"},
expectedError: fmt.Errorf("get GitHub access token: some error"),
},
"returns error if fail to parse repo name out of CodeCommit URL": {
inEnvironments: []string{},
inGitHubAccessToken: "",
Expand Down Expand Up @@ -599,8 +559,8 @@ func TestInitPipelineOpts_Execute(t *testing.T) {

expectedError error
}{
"creates secret and writes manifest and buildspecs for GH provider": {
inProvider: "GitHub",
"creates secret and writes manifest and buildspec for GHV1 provider": {
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand Down Expand Up @@ -641,18 +601,56 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
},
expectedError: nil,
},
"creates secret and writes manifest and buildspecs for CC provider": {
"writes manifest and buildspec for GH(v2) provider": {
inProvider: "CodeCommit",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Prod: false,
},
},
inRepoName: "goose",
inBranch: "main",
inAppName: "badgoose",
inGitHubToken: "",
inRepoName: "goose",
inBranch: "main",
inAppName: "badgoose",

mockSecretsManager: func(m *mocks.MocksecretsManager) {},
mockWsWriter: func(m *mocks.MockwsPipelineWriter) {
m.EXPECT().WritePipelineManifest(gomock.Any()).Return("/pipeline.yml", nil)
m.EXPECT().WritePipelineBuildspec(gomock.Any()).Return("/buildspec.yml", nil)
},
mockParser: func(m *templatemocks.MockParser) {
m.EXPECT().Parse(buildspecTemplatePath, gomock.Any()).Return(&template.Content{
Buffer: bytes.NewBufferString("hello"),
}, nil)
},
mockStoreSvc: func(m *mocks.Mockstore) {
m.EXPECT().GetApplication("badgoose").Return(&config.Application{
Name: "badgoose",
}, nil)
},
mockRegionalResourcesGetter: func(m *mocks.MockappResourcesGetter) {
m.EXPECT().GetRegionalAppResources(&config.Application{
Name: "badgoose",
}).Return([]*stack.AppRegionalResources{
{
Region: "us-west-2",
S3Bucket: "gooseBucket",
},
}, nil)
},
expectedError: nil,
},
"writes manifest and buildspec for CC provider": {
inProvider: "CodeCommit",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Prod: false,
},
},
inRepoName: "goose",
inBranch: "main",
inAppName: "badgoose",

mockSecretsManager: func(m *mocks.MocksecretsManager) {},
mockWsWriter: func(m *mocks.MockwsPipelineWriter) {
Expand Down Expand Up @@ -681,7 +679,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
},
expectedError: nil,
},
"creates secret and writes manifest and buildspecs for BB provider": {
"writes manifest and buildspec for BB provider": {
inProvider: "Bitbucket",
inEnvConfigs: []*config.Environment{
{
Expand Down Expand Up @@ -721,7 +719,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
expectedError: nil,
},
"does not return an error if secret already exists": {
inProvider: "GitHub",
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand Down Expand Up @@ -765,7 +763,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
expectedError: nil,
},
"returns an error if can't write manifest": {
inProvider: "GitHub",
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand All @@ -789,7 +787,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
expectedError: errors.New("write pipeline manifest to workspace: some error"),
},
"returns an error if application cannot be retrieved": {
inProvider: "GitHub",
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand All @@ -815,7 +813,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
expectedError: errors.New("get application badgoose: some error"),
},
"returns an error if can't get regional application resources": {
inProvider: "GitHub",
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand Down Expand Up @@ -847,7 +845,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
expectedError: fmt.Errorf("get regional application resources: some error"),
},
"returns an error if buildspec cannot be parsed": {
inProvider: "GitHub",
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand Down Expand Up @@ -887,7 +885,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
expectedError: errors.New("some error"),
},
"does not return an error if buildspec and manifest already exists": {
inProvider: "GitHub",
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand Down Expand Up @@ -929,7 +927,7 @@ func TestInitPipelineOpts_Execute(t *testing.T) {
expectedError: nil,
},
"returns an error if can't write buildspec": {
inProvider: "GitHub",
inProvider: "GitHubV1",
inEnvConfigs: []*config.Environment{
{
Name: "test",
Expand Down
Loading