Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit10ccce1

Browse files
committed
feat: expose 30d trial form via CLI
1 parent79d24d2 commit10ccce1

File tree

5 files changed

+359
-1
lines changed

5 files changed

+359
-1
lines changed

‎cli/login.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ func (r *RootCmd) login() *serpent.Command {
149149
passwordstring
150150
trialbool
151151
useTokenForSessionbool
152+
153+
firstNamestring
154+
lastNamestring
155+
phoneNumberstring
156+
jobTitlestring
157+
companyNamestring
158+
countrystring
159+
developersstring
152160
)
153161
cmd:=&serpent.Command{
154162
Use:"login [<url>]",
@@ -267,12 +275,66 @@ func (r *RootCmd) login() *serpent.Command {
267275
trial=v=="yes"||v=="y"
268276
}
269277

278+
iftrial {
279+
iffirstName=="" {
280+
firstName,err=promptTrialInfo(inv,"firstName")
281+
iferr!=nil {
282+
returnerr
283+
}
284+
}
285+
iflastName=="" {
286+
lastName,err=promptTrialInfo(inv,"lastName")
287+
iferr!=nil {
288+
returnerr
289+
}
290+
}
291+
ifphoneNumber=="" {
292+
phoneNumber,err=promptTrialInfo(inv,"phoneNumber")
293+
iferr!=nil {
294+
returnerr
295+
}
296+
}
297+
ifjobTitle=="" {
298+
jobTitle,err=promptTrialInfo(inv,"jobTitle")
299+
iferr!=nil {
300+
returnerr
301+
}
302+
}
303+
ifcompanyName=="" {
304+
companyName,err=promptTrialInfo(inv,"companyName")
305+
iferr!=nil {
306+
returnerr
307+
}
308+
}
309+
ifcountry=="" {
310+
country,err=promptCountry(inv)
311+
iferr!=nil {
312+
returnerr
313+
}
314+
}
315+
ifdevelopers=="" {
316+
developers,err=promptDevelopers(inv)
317+
iferr!=nil {
318+
returnerr
319+
}
320+
}
321+
}
322+
270323
_,err=client.CreateFirstUser(ctx, codersdk.CreateFirstUserRequest{
271324
Email:email,
272325
Username:username,
273326
Name:name,
274327
Password:password,
275328
Trial:trial,
329+
TrialInfo: codersdk.CreateFirstUserTrialInfo{
330+
FirstName:firstName,
331+
LastName:lastName,
332+
PhoneNumber:phoneNumber,
333+
JobTitle:jobTitle,
334+
CompanyName:companyName,
335+
Country:country,
336+
Developers:developers,
337+
},
276338
})
277339
iferr!=nil {
278340
returnxerrors.Errorf("create initial user: %w",err)
@@ -398,6 +460,48 @@ func (r *RootCmd) login() *serpent.Command {
398460
Description:"By default, the CLI will generate a new session token when logging in. This flag will instead use the provided token as the session token.",
399461
Value:serpent.BoolOf(&useTokenForSession),
400462
},
463+
{
464+
Flag:"first-user-first-name",
465+
Env:"CODER_FIRST_USER_FIRST_NAME",
466+
Description:"Specifies the first name of the user.",
467+
Value:serpent.StringOf(&firstName),
468+
},
469+
{
470+
Flag:"first-user-last-name",
471+
Env:"CODER_FIRST_USER_LAST_NAME",
472+
Description:"Specifies the last name of the user.",
473+
Value:serpent.StringOf(&lastName),
474+
},
475+
{
476+
Flag:"first-user-phone-number",
477+
Env:"CODER_FIRST_USER_PHONE_NUMBER",
478+
Description:"Specifies the phone number of the user.",
479+
Value:serpent.StringOf(&phoneNumber),
480+
},
481+
{
482+
Flag:"first-user-job-title",
483+
Env:"CODER_FIRST_USER_JOB_TITLE",
484+
Description:"Specifies the job title of the user.",
485+
Value:serpent.StringOf(&jobTitle),
486+
},
487+
{
488+
Flag:"first-user-company-name",
489+
Env:"CODER_FIRST_USER_COMPANY_NAME",
490+
Description:"Specifies the company name of the user.",
491+
Value:serpent.StringOf(&companyName),
492+
},
493+
{
494+
Flag:"first-user-country",
495+
Env:"CODER_FIRST_USER_COUNTRY",
496+
Description:"Specifies the country of the user.",
497+
Value:serpent.StringOf(&country),
498+
},
499+
{
500+
Flag:"first-user-developers",
501+
Env:"CODER_FIRST_USER_DEVELOPERS",
502+
Description:"Specifies the number of developers.",
503+
Value:serpent.StringOf(&developers),
504+
},
401505
}
402506
returncmd
403507
}
@@ -449,3 +553,75 @@ func openURL(inv *serpent.Invocation, urlToOpen string) error {
449553

450554
returnbrowser.OpenURL(urlToOpen)
451555
}
556+
557+
funcpromptTrialInfo(inv*serpent.Invocation,fieldNamestring) (string,error) {
558+
value,err:=cliui.Prompt(inv, cliui.PromptOptions{
559+
Text:fmt.Sprintf("Please enter %s:",pretty.Sprint(cliui.DefaultStyles.Field,fieldName)),
560+
Validate:func(sstring)error {
561+
ifstrings.TrimSpace(s)=="" {
562+
returnxerrors.Errorf("%s is required",fieldName)
563+
}
564+
returnnil
565+
},
566+
})
567+
iferr!=nil {
568+
iferrors.Is(err,cliui.Canceled) {
569+
return"",nil
570+
}
571+
return"",err
572+
}
573+
returnvalue,nil
574+
}
575+
576+
funcpromptDevelopers(inv*serpent.Invocation) (string,error) {
577+
options:= []string{"1-100","101-500","501-1000","1001-2500","2500+"}
578+
selection,err:=cliui.Select(inv, cliui.SelectOptions{
579+
Options:options,
580+
HideSearch:false,
581+
Message:"Select the number of developers:",
582+
})
583+
iferr!=nil {
584+
return"",xerrors.Errorf("select developers: %w",err)
585+
}
586+
returnselection,nil
587+
}
588+
589+
funcpromptCountry(inv*serpent.Invocation) (string,error) {
590+
countries:= []string{
591+
"Afghanistan","Åland Islands","Albania","Algeria","American Samoa","Andorra","Angola","Anguilla","Antarctica","Antigua and Barbuda",
592+
"Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados",
593+
"Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia, Plurinational State of","Bonaire, Sint Eustatius and Saba","Bosnia and Herzegovina","Botswana",
594+
"Bouvet Island","Brazil","British Indian Ocean Territory","Brunei Darussalam","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada",
595+
"Cape Verde","Cayman Islands","Central African Republic","Chad","Chile","China","Christmas Island","Cocos (Keeling) Islands","Colombia","Comoros",
596+
"Congo","Congo, the Democratic Republic of the","Cook Islands","Costa Rica","Côte d'Ivoire","Croatia","Cuba","Curaçao","Cyprus","Czech Republic",
597+
"Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia",
598+
"Ethiopia","Falkland Islands (Malvinas)","Faroe Islands","Fiji","Finland","France","French Guiana","French Polynesia","French Southern Territories","Gabon",
599+
"Gambia","Georgia","Germany","Ghana","Gibraltar","Greece","Greenland","Grenada","Guadeloupe","Guam",
600+
"Guatemala","Guernsey","Guinea","Guinea-Bissau","Guyana","Haiti","Heard Island and McDonald Islands","Holy See (Vatican City State)","Honduras","Hong Kong",
601+
"Hungary","Iceland","India","Indonesia","Iran, Islamic Republic of","Iraq","Ireland","Isle of Man","Israel","Italy",
602+
"Jamaica","Japan","Jersey","Jordan","Kazakhstan","Kenya","Kiribati","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
603+
"Kyrgyzstan","Lao People's Democratic Republic","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg",
604+
"Macao","Macedonia, the Former Yugoslav Republic of","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Martinique",
605+
"Mauritania","Mauritius","Mayotte","Mexico","Micronesia, Federated States of","Moldova, Republic of","Monaco","Mongolia","Montenegro","Montserrat",
606+
"Morocco","Mozambique","Myanmar","Namibia","Nauru","Nepal","Netherlands","New Caledonia","New Zealand","Nicaragua",
607+
"Niger","Nigeria","Niue","Norfolk Island","Northern Mariana Islands","Norway","Oman","Pakistan","Palau","Palestine, State of",
608+
"Panama","Papua New Guinea","Paraguay","Peru","Philippines","Pitcairn","Poland","Portugal","Puerto Rico","Qatar",
609+
"Réunion","Romania","Russian Federation","Rwanda","Saint Barthélemy","Saint Helena, Ascension and Tristan da Cunha","Saint Kitts and Nevis","Saint Lucia","Saint Martin (French part)","Saint Pierre and Miquelon",
610+
"Saint Vincent and the Grenadines","Samoa","San Marino","Sao Tome and Principe","Saudi Arabia","Senegal","Serbia","Seychelles","Sierra Leone","Singapore",
611+
"Sint Maarten (Dutch part)","Slovakia","Slovenia","Solomon Islands","Somalia","South Africa","South Georgia and the South Sandwich Islands","South Sudan","Spain","Sri Lanka",
612+
"Sudan","Suriname","Svalbard and Jan Mayen","Swaziland","Sweden","Switzerland","Syrian Arab Republic","Taiwan, Province of China","Tajikistan","Tanzania, United Republic of",
613+
"Thailand","Timor-Leste","Togo","Tokelau","Tonga","Trinidad and Tobago","Tunisia","Turkey","Turkmenistan","Turks and Caicos Islands",
614+
"Tuvalu","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","United States Minor Outlying Islands","Uruguay","Uzbekistan","Vanuatu",
615+
"Venezuela, Bolivarian Republic of","Viet Nam","Virgin Islands, British","Virgin Islands, U.S.","Wallis and Futuna","Western Sahara","Yemen","Zambia","Zimbabwe",
616+
}
617+
618+
selection,err:=cliui.Select(inv, cliui.SelectOptions{
619+
Options:countries,
620+
Message:"Select the country:",
621+
HideSearch:false,
622+
})
623+
iferr!=nil {
624+
return"",xerrors.Errorf("select country: %w",err)
625+
}
626+
returnselection,nil
627+
}

‎cli/login_test.go

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,58 @@ func TestLogin(t *testing.T) {
9696
"password",coderdtest.FirstUserParams.Password,
9797
"password",coderdtest.FirstUserParams.Password,// confirm
9898
"trial","yes",
99+
"firstName",coderdtest.TrialUserParams.FirstName,
100+
"lastName",coderdtest.TrialUserParams.LastName,
101+
"phoneNumber",coderdtest.TrialUserParams.PhoneNumber,
102+
"jobTitle",coderdtest.TrialUserParams.JobTitle,
103+
"companyName",coderdtest.TrialUserParams.CompanyName,
104+
// `developers` and `country` `cliui.Select` automatically selects the first option during tests.
105+
}
106+
fori:=0;i<len(matches);i+=2 {
107+
match:=matches[i]
108+
value:=matches[i+1]
109+
pty.ExpectMatch(match)
110+
pty.WriteLine(value)
111+
}
112+
pty.ExpectMatch("Welcome to Coder")
113+
<-doneChan
114+
ctx:=testutil.Context(t,testutil.WaitShort)
115+
resp,err:=client.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
116+
Email:coderdtest.FirstUserParams.Email,
117+
Password:coderdtest.FirstUserParams.Password,
118+
})
119+
require.NoError(t,err)
120+
client.SetSessionToken(resp.SessionToken)
121+
me,err:=client.User(ctx,codersdk.Me)
122+
require.NoError(t,err)
123+
assert.Equal(t,coderdtest.FirstUserParams.Username,me.Username)
124+
assert.Equal(t,coderdtest.FirstUserParams.Name,me.Name)
125+
assert.Equal(t,coderdtest.FirstUserParams.Email,me.Email)
126+
})
127+
128+
t.Run("InitialUserTTYWithNoTrial",func(t*testing.T) {
129+
t.Parallel()
130+
client:=coderdtest.New(t,nil)
131+
// The --force-tty flag is required on Windows, because the `isatty` library does not
132+
// accurately detect Windows ptys when they are not attached to a process:
133+
// https://github.com/mattn/go-isatty/issues/59
134+
doneChan:=make(chanstruct{})
135+
root,_:=clitest.New(t,"login","--force-tty",client.URL.String())
136+
pty:=ptytest.New(t).Attach(root)
137+
gofunc() {
138+
deferclose(doneChan)
139+
err:=root.Run()
140+
assert.NoError(t,err)
141+
}()
142+
143+
matches:= []string{
144+
"first user?","yes",
145+
"username",coderdtest.FirstUserParams.Username,
146+
"name",coderdtest.FirstUserParams.Name,
147+
"email",coderdtest.FirstUserParams.Email,
148+
"password",coderdtest.FirstUserParams.Password,
149+
"password",coderdtest.FirstUserParams.Password,// confirm
150+
"trial","no",
99151
}
100152
fori:=0;i<len(matches);i+=2 {
101153
match:=matches[i]
@@ -142,6 +194,12 @@ func TestLogin(t *testing.T) {
142194
"password",coderdtest.FirstUserParams.Password,
143195
"password",coderdtest.FirstUserParams.Password,// confirm
144196
"trial","yes",
197+
"firstName",coderdtest.TrialUserParams.FirstName,
198+
"lastName",coderdtest.TrialUserParams.LastName,
199+
"phoneNumber",coderdtest.TrialUserParams.PhoneNumber,
200+
"jobTitle",coderdtest.TrialUserParams.JobTitle,
201+
"companyName",coderdtest.TrialUserParams.CompanyName,
202+
// `developers` and `country` `cliui.Select` automatically selects the first option during tests.
145203
}
146204
fori:=0;i<len(matches);i+=2 {
147205
match:=matches[i]
@@ -185,6 +243,12 @@ func TestLogin(t *testing.T) {
185243
"password",coderdtest.FirstUserParams.Password,
186244
"password",coderdtest.FirstUserParams.Password,// confirm
187245
"trial","yes",
246+
"firstName",coderdtest.TrialUserParams.FirstName,
247+
"lastName",coderdtest.TrialUserParams.LastName,
248+
"phoneNumber",coderdtest.TrialUserParams.PhoneNumber,
249+
"jobTitle",coderdtest.TrialUserParams.JobTitle,
250+
"companyName",coderdtest.TrialUserParams.CompanyName,
251+
// `developers` and `country` `cliui.Select` automatically selects the first option during tests.
188252
}
189253
fori:=0;i<len(matches);i+=2 {
190254
match:=matches[i]
@@ -217,6 +281,13 @@ func TestLogin(t *testing.T) {
217281
"--first-user-email",coderdtest.FirstUserParams.Email,
218282
"--first-user-password",coderdtest.FirstUserParams.Password,
219283
"--first-user-trial",
284+
"--first-user-first-name",coderdtest.TrialUserParams.FirstName,
285+
"--first-user-last-name",coderdtest.TrialUserParams.LastName,
286+
"--first-user-phone-number",coderdtest.TrialUserParams.PhoneNumber,
287+
"--first-user-job-title",coderdtest.TrialUserParams.JobTitle,
288+
"--first-user-company-name",coderdtest.TrialUserParams.CompanyName,
289+
"--first-user-country",coderdtest.TrialUserParams.Country,
290+
"--first-user-developers",coderdtest.TrialUserParams.Developers,
220291
)
221292
pty:=ptytest.New(t).Attach(inv)
222293
w:=clitest.StartWithWaiter(t,inv)
@@ -245,6 +316,14 @@ func TestLogin(t *testing.T) {
245316
"--first-user-email",coderdtest.FirstUserParams.Email,
246317
"--first-user-password",coderdtest.FirstUserParams.Password,
247318
"--first-user-trial",
319+
"--first-user-first-name",coderdtest.TrialUserParams.FirstName,
320+
"--first-user-last-name",coderdtest.TrialUserParams.LastName,
321+
"--first-user-phone-number",coderdtest.TrialUserParams.PhoneNumber,
322+
"--first-user-job-title",coderdtest.TrialUserParams.JobTitle,
323+
"--first-user-company-name",coderdtest.TrialUserParams.CompanyName,
324+
"--first-user-country",coderdtest.TrialUserParams.Country,
325+
"--first-user-developers",coderdtest.TrialUserParams.Developers,
326+
// `developers` and `country` `cliui.Select` automatically selects the first option during tests.
248327
)
249328
pty:=ptytest.New(t).Attach(inv)
250329
w:=clitest.StartWithWaiter(t,inv)
@@ -299,12 +378,21 @@ func TestLogin(t *testing.T) {
299378
// Validate that we reprompt for matching passwords.
300379
pty.ExpectMatch("Passwords do not match")
301380
pty.ExpectMatch("Enter a "+pretty.Sprint(cliui.DefaultStyles.Field,"password"))
302-
303381
pty.WriteLine(coderdtest.FirstUserParams.Password)
304382
pty.ExpectMatch("Confirm")
305383
pty.WriteLine(coderdtest.FirstUserParams.Password)
306384
pty.ExpectMatch("trial")
307385
pty.WriteLine("yes")
386+
pty.ExpectMatch("firstName")
387+
pty.WriteLine(coderdtest.TrialUserParams.FirstName)
388+
pty.ExpectMatch("lastName")
389+
pty.WriteLine(coderdtest.TrialUserParams.LastName)
390+
pty.ExpectMatch("phoneNumber")
391+
pty.WriteLine(coderdtest.TrialUserParams.PhoneNumber)
392+
pty.ExpectMatch("jobTitle")
393+
pty.WriteLine(coderdtest.TrialUserParams.JobTitle)
394+
pty.ExpectMatch("companyName")
395+
pty.WriteLine(coderdtest.TrialUserParams.CompanyName)
308396
pty.ExpectMatch("Welcome to Coder")
309397
<-doneChan
310398
})

‎cli/testdata/coder_login_--help.golden

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,38 @@ USAGE:
66
Authenticate with Coder deployment
77

88
OPTIONS:
9+
--first-user-company-name string, $CODER_FIRST_USER_COMPANY_NAME
10+
Specifies the company name of the user.
11+
12+
--first-user-country string, $CODER_FIRST_USER_COUNTRY
13+
Specifies the country of the user.
14+
15+
--first-user-developers string, $CODER_FIRST_USER_DEVELOPERS
16+
Specifies the number of developers.
17+
918
--first-user-email string, $CODER_FIRST_USER_EMAIL
1019
Specifies an email address to use if creating the first user for the
1120
deployment.
1221

22+
--first-user-first-name string, $CODER_FIRST_USER_FIRST_NAME
23+
Specifies the first name of the user.
24+
1325
--first-user-full-name string, $CODER_FIRST_USER_FULL_NAME
1426
Specifies a human-readable name for the first user of the deployment.
1527

28+
--first-user-job-title string, $CODER_FIRST_USER_JOB_TITLE
29+
Specifies the job title of the user.
30+
31+
--first-user-last-name string, $CODER_FIRST_USER_LAST_NAME
32+
Specifies the last name of the user.
33+
1634
--first-user-password string, $CODER_FIRST_USER_PASSWORD
1735
Specifies a password to use if creating the first user for the
1836
deployment.
1937

38+
--first-user-phone-number string, $CODER_FIRST_USER_PHONE_NUMBER
39+
Specifies the phone number of the user.
40+
2041
--first-user-trial bool, $CODER_FIRST_USER_TRIAL
2142
Specifies whether a trial license should be provisioned for the Coder
2243
deployment or not.

‎coderd/coderdtest/coderdtest.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,16 @@ var FirstUserParams = codersdk.CreateFirstUserRequest{
651651
Name:"Test User",
652652
}
653653

654+
varTrialUserParams= codersdk.CreateFirstUserTrialInfo{
655+
FirstName:"John",
656+
LastName:"Doe",
657+
PhoneNumber:"9999999999",
658+
JobTitle:"Engineer",
659+
CompanyName:"Acme Inc",
660+
Country:"United States",
661+
Developers:"10-50",
662+
}
663+
654664
// CreateFirstUser creates a user with preset credentials and authenticates
655665
// with the passed in codersdk client.
656666
funcCreateFirstUser(t testing.TB,client*codersdk.Client) codersdk.CreateFirstUserResponse {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp