Skip to content

Commit 5da9445

Browse files
authored
Merge pull request #1139 from CircleCI-Public/life-1571/check-for-sources-repo
[Life 1571] Trigger Create | Only prompt users to supply `checkout_ref` & `config_ref` if differnt from the pipeline repo
2 parents fedb229 + 1222a0a commit 5da9445

File tree

4 files changed

+123
-31
lines changed

4 files changed

+123
-31
lines changed

api/trigger/trigger.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ type CreateTriggerInfo struct {
55
Name string
66
}
77

8+
type GetPipelineDefinitionOptions struct {
9+
ProjectID string
10+
PipelineDefinitionID string
11+
}
12+
813
// TriggerClient is the interface to interact with trigger
914
type TriggerClient interface {
1015
CreateTrigger(options CreateTriggerOptions) (*CreateTriggerInfo, error)
16+
GetPipelineDefinition(options GetPipelineDefinitionOptions) (*PipelineDefinition, error)
1117
}

api/trigger/trigger_rest.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"net/url"
66

7+
"github.com/CircleCI-Public/circleci-cli/api/pipeline"
78
"github.com/CircleCI-Public/circleci-cli/api/rest"
89
"github.com/CircleCI-Public/circleci-cli/settings"
910
)
@@ -99,3 +100,36 @@ func (c *triggerRestClient) CreateTrigger(options CreateTriggerOptions) (*Create
99100
Name: resp.Name,
100101
}, nil
101102
}
103+
104+
type PipelineDefinition struct {
105+
ConfigSourceId string
106+
CheckoutSourceId string
107+
}
108+
109+
type GetPipelineDefinitionResponse struct {
110+
ID string `json:"id"`
111+
Name string `json:"name"`
112+
Description string `json:"description"`
113+
CreatedAt string `json:"created_at"`
114+
ConfigSource pipeline.ConfigSourceResponse `json:"config_source"`
115+
CheckoutSource pipeline.CheckoutSourceResponse `json:"checkout_source"`
116+
}
117+
118+
func (c *triggerRestClient) GetPipelineDefinition(options GetPipelineDefinitionOptions) (*PipelineDefinition, error) {
119+
path := fmt.Sprintf("projects/%s/pipeline-definitions/%s", options.ProjectID, options.PipelineDefinitionID)
120+
req, err := c.client.NewRequest("GET", &url.URL{Path: path}, nil)
121+
if err != nil {
122+
return nil, err
123+
}
124+
125+
var resp GetPipelineDefinitionResponse
126+
_, err = c.client.DoRequest(req, &resp)
127+
if err != nil {
128+
return nil, err
129+
}
130+
131+
return &PipelineDefinition{
132+
ConfigSourceId: resp.ConfigSource.Repo.ExternalID,
133+
CheckoutSourceId: resp.CheckoutSource.Repo.ExternalID,
134+
}, nil
135+
}

cmd/trigger/create.go

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,47 @@ func newCreateCommand(ops *triggerOpts, preRunE validator.Validator) *cobra.Comm
2020
Use: "create <project-id> [--name <trigger-name>] [--description <description>] [--repo-id <github-repo-id>] [--event-preset <preset-to-filter-triggers>] [--config-ref <ref-to-fetch-config>] [--checkout-ref <ref-to-checkout-code>]",
2121
Short: "Create a new trigger for a CircleCI project.",
2222
Long: `Create a new trigger for a CircleCI project.
23-
All flags are optional - if not provided, you will be prompted interactively for the required values:
24-
--pipeline-definition-id Pipeline definition ID you wish to create a trigger for (required)
25-
--name Name of the trigger (required)
26-
--description Description of the trigger (will not prompt if omitted)
27-
--repo-id GitHub repository ID you wish to create a trigger for (required)
28-
--event-preset The name of the event preset to use when filtering events for this trigger (will not prompt if omitted)
29-
--checkout-ref Git ref (branch, or tag for example) to check out code for pipeline runs (only required if different repository, will not prompt if omitted)
30-
--config-ref Git ref (branch, or tag for example) to fetch config for pipeline runs (only required if different repository, will not prompt if omitted)
31-
To api/v2 documentation for creating a trigger, see: https://circleci.com/docs/api/v2/index.html#tag/Trigger/operation/createTrigger
23+
24+
All flags are optional - if not provided, you will be prompted interactively for
25+
the required values:
26+
27+
--pipeline-definition-id Pipeline definition ID you wish to create a trigger for
28+
(required)
29+
--name Name of the trigger (required)
30+
--description Description of the trigger (will not prompt if omitted)
31+
--repo-id GitHub repository ID you wish to create a trigger for
32+
(required)
33+
--event-preset The name of the event preset to use when filtering events
34+
for this trigger (will not prompt if omitted)
35+
--checkout-ref Git ref (branch, or tag for example) to check out code
36+
for pipeline runs (only required if different repository,
37+
will not prompt if omitted)
38+
--config-ref Git ref (branch, or tag for example) to fetch config for
39+
pipeline runs (only required if different repository,
40+
will not prompt if omitted)
41+
42+
To api/v2 documentation for creating a trigger, see:
43+
https://circleci.com/docs/api/v2/index.html#tag/Trigger/operation/createTrigger
3244
3345
Examples:
3446
# Minimal usage (will prompt for required values):
3547
circleci trigger create 1662d941-6e28-43ab-bea2-aa678c098d4c
36-
48+
3749
# Full usage with all flags:
38-
circleci trigger create 1662d941-6e28-43ab-bea2-aa678c098d4c --name my-trigger --description "Trigger description" --repo-id 123456 --event-preset all-pushes --config-ref my-config --checkout-ref my-checkout
39-
Note: This is only supporting pipeline definitions created with GitHub App provider. You will need our GitHub App installed in your repository.
40-
Note: To get the repository id you can use https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#get-a-repository
41-
Note: To get the pipeline definition id you can visit the Pipelines tab in project settings: https://app.circleci.com/settings/project/circleci/<org>/<project>/configurations
42-
Note: --config_ref and --checkout_ref flags are only required if your config source or checkout source exist in a different repo to your trigger repo
50+
circleci trigger create 1662d941-6e28-43ab-bea2-aa678c098d4c --name my-trigger \
51+
--description "Trigger description" --repo-id 123456 --event-preset all-pushes \
52+
--config-ref my-config --checkout-ref my-checkout
53+
54+
Notes:
55+
- This is only supporting pipeline definitions created with GitHub App provider.
56+
You will need our GitHub App installed in your repository.
57+
- To get the repository id you can use:
58+
https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#get-a-repository
59+
- To get the pipeline definition id you can visit the Pipelines tab in project
60+
settings:
61+
https://app.circleci.com/settings/project/circleci/<org>/<project>/configurations
62+
- --config_ref and --checkout_ref flags are only required if your config source or
63+
checkout source exist in a different repo to your trigger repo
4364
`,
4465
PreRunE: preRunE,
4566
RunE: func(cmd *cobra.Command, args []string) error {
@@ -60,22 +81,26 @@ Note: --config_ref and --checkout_ref flags are only required if your config sou
6081
repoID = ops.reader.ReadStringFromUser(repoPrompt)
6182
}
6283

63-
if configRef == "" {
64-
refPrompt := "Is your config source source repository different to the repository for this trigger (y/n)?"
65-
refPromptResponse := ops.reader.ReadStringFromUser(refPrompt)
66-
if refPromptResponse == "y" {
67-
configRefPrompt := "Enter the branch or tag to use when fetching config for pipeline runs created from this trigger"
68-
configRef = ops.reader.ReadStringFromUser(configRefPrompt)
69-
}
84+
pipelineOptions := trigger.GetPipelineDefinitionOptions{
85+
ProjectID: projectID,
86+
PipelineDefinitionID: pipelineDefinitionID,
87+
}
88+
pipelineResp, pipelineErr := ops.triggerClient.GetPipelineDefinition(pipelineOptions)
89+
90+
if pipelineErr != nil {
91+
cmd.Println("\nThere was an error fetching your pipeline definition")
92+
return pipelineErr
93+
}
94+
95+
if configRef == "" && pipelineResp.ConfigSourceId != repoID {
96+
configRefPrompt := "Your pipeline repo and config source repo are different. Enter the branch or tag to use when fetching config for pipeline runs"
97+
configRef = ops.reader.ReadStringFromUser(configRefPrompt)
98+
7099
}
71100

72-
if checkoutRef == "" {
73-
refPrompt := "Is your checkout source repository different to the repository for this trigger (y/n)?"
74-
refPromptResponse := ops.reader.ReadStringFromUser(refPrompt)
75-
if refPromptResponse == "y" {
76-
checkoutRefPrompt := "Enter the branch or tag to use when checking out code for pipeline runs created from this trigger"
77-
checkoutRef = ops.reader.ReadStringFromUser(checkoutRefPrompt)
78-
}
101+
if checkoutRef == "" && pipelineResp.CheckoutSourceId != repoID {
102+
checkoutRefPrompt := "Your pipeline repo and checkout source repo are different. Enter the branch or tag to use when checking out code for pipeline runs"
103+
checkoutRef = ops.reader.ReadStringFromUser(checkoutRefPrompt)
79104
}
80105

81106
triggerOptions := trigger.CreateTriggerOptions{

cmd/trigger/trigger_test.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,35 @@ func TestCreateTrigger(t *testing.T) {
117117
for _, tt := range tests {
118118
t.Run(tt.name, func(t *testing.T) {
119119
var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
120+
w.Header().Set("Content-Type", "application/json")
121+
122+
if r.Method == "GET" {
123+
// Handle GET request for pipeline definition
124+
assert.Equal(t, r.URL.String(), fmt.Sprintf("/projects/%s/pipeline-definitions/%s", tt.args.projectID, tt.args.pipelineDefinitionID))
125+
126+
responseBody := map[string]interface{}{
127+
"id": tt.args.pipelineDefinitionID,
128+
"name": "Test Pipeline",
129+
"config_source": map[string]interface{}{
130+
"repo": map[string]interface{}{
131+
"external_id": tt.args.repoID,
132+
},
133+
},
134+
"checkout_source": map[string]interface{}{
135+
"repo": map[string]interface{}{
136+
"external_id": tt.args.repoID,
137+
},
138+
},
139+
}
140+
responseJSON, err := json.Marshal(responseBody)
141+
assert.NilError(t, err)
142+
w.WriteHeader(http.StatusOK)
143+
_, err = w.Write(responseJSON)
144+
assert.NilError(t, err)
145+
return
146+
}
147+
148+
// Handle POST request for trigger creation
120149
assert.Equal(t, r.Method, "POST")
121150
assert.Equal(t, r.URL.String(), fmt.Sprintf("/projects/%s/pipeline-definitions/%s/triggers", tt.args.projectID, tt.args.pipelineDefinitionID))
122151

@@ -138,11 +167,9 @@ func TestCreateTrigger(t *testing.T) {
138167
expectedRepoID := tt.args.repoID
139168
assert.Equal(t, repo["external_id"].(string), expectedRepoID)
140169

141-
w.Header().Set("Content-Type", "application/json")
142170
w.WriteHeader(tt.args.statusCode)
143171

144172
if tt.args.statusCode == http.StatusOK {
145-
146173
responseBody := map[string]interface{}{
147174
"id": "trigger-id",
148175
"name": tt.args.triggerName,

0 commit comments

Comments
 (0)