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

Commitccd0616

Browse files
authored
feat: Add built-in PostgreSQL for simple production setup (#2345)
* feat: Add built-in PostgreSQL for simple production setupFixes#2321.* Use fork of embedded-postgres for cache path
1 parentbb4ecd7 commitccd0616

File tree

23 files changed

+408
-475
lines changed

23 files changed

+408
-475
lines changed

‎.goreleaser.yaml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ nfpms:
9393
type:"config|noreplace"
9494
-src:coder.service
9595
dst:/usr/lib/systemd/system/coder.service
96+
scripts:
97+
preinstall:preinstall.sh
9698

9799
# Image templates are empty on snapshots to avoid lengthy builds for development.
98100
dockers:

‎README.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@ To install, run:
4747
curl -fsSL https://coder.com/install.sh| sh
4848
```
4949

50-
Once installed, you canrun atemporary deploymentin dev mode (all data is in-memory and destroyed on exit):
50+
Once installed, you canstart aproduction deploymentwith a single command:
5151

5252
```sh
53-
coder server --dev
53+
# Automatically sets up an external access URL on *.try.coder.app
54+
coder server --tunnel
55+
56+
# Requires a PostgreSQL instance and external access URL
57+
coder server --postgres-url<url> --access-url<url>
5458
```
5559

5660
Use`coder --help` to get a complete list of flags and environment variables. Use our[quickstart guide](https://coder.com/docs/coder-oss/latest/quickstart) for a full walkthrough.

‎cli/config/file.go‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ func (r Root) DotfilesURL() File {
2525
returnFile(filepath.Join(string(r),"dotfilesurl"))
2626
}
2727

28+
func (rRoot)PostgresPath()string {
29+
returnfilepath.Join(string(r),"postgres")
30+
}
31+
32+
func (rRoot)PostgresPassword()File {
33+
returnFile(filepath.Join(r.PostgresPath(),"password"))
34+
}
35+
36+
func (rRoot)PostgresPort()File {
37+
returnFile(filepath.Join(r.PostgresPath(),"port"))
38+
}
39+
2840
// File provides convenience methods for interacting with *os.File.
2941
typeFilestring
3042

‎cli/login.go‎

Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/spf13/cobra"
1818
"golang.org/x/xerrors"
1919

20+
"github.com/coder/coder/cli/cliflag"
2021
"github.com/coder/coder/cli/cliui"
2122
"github.com/coder/coder/codersdk"
2223
)
@@ -37,7 +38,12 @@ func init() {
3738
}
3839

3940
funclogin()*cobra.Command {
40-
return&cobra.Command{
41+
var (
42+
emailstring
43+
usernamestring
44+
passwordstring
45+
)
46+
cmd:=&cobra.Command{
4147
Use:"login <url>",
4248
Short:"Authenticate with a Coder deployment",
4349
Args:cobra.ExactArgs(1),
@@ -66,71 +72,77 @@ func login() *cobra.Command {
6672
returnxerrors.Errorf("has initial user: %w",err)
6773
}
6874
if!hasInitialUser {
69-
if!isTTY(cmd) {
70-
returnxerrors.New("the initial user cannot be created in non-interactive mode. use the API")
71-
}
7275
_,_=fmt.Fprintf(cmd.OutOrStdout(),caret+"Your Coder deployment hasn't been set up!\n")
7376

74-
_,err:=cliui.Prompt(cmd, cliui.PromptOptions{
75-
Text:"Would you like to create the first user?",
76-
Default:"yes",
77-
IsConfirm:true,
78-
})
79-
iferrors.Is(err,cliui.Canceled) {
80-
returnnil
81-
}
82-
iferr!=nil {
83-
returnerr
84-
}
85-
currentUser,err:=user.Current()
86-
iferr!=nil {
87-
returnxerrors.Errorf("get current user: %w",err)
88-
}
89-
username,err:=cliui.Prompt(cmd, cliui.PromptOptions{
90-
Text:"What "+cliui.Styles.Field.Render("username")+" would you like?",
91-
Default:currentUser.Username,
92-
})
93-
iferrors.Is(err,cliui.Canceled) {
94-
returnnil
95-
}
96-
iferr!=nil {
97-
returnxerrors.Errorf("pick username prompt: %w",err)
98-
}
99-
100-
email,err:=cliui.Prompt(cmd, cliui.PromptOptions{
101-
Text:"What's your "+cliui.Styles.Field.Render("email")+"?",
102-
Validate:func(sstring)error {
103-
err:=validator.New().Var(s,"email")
104-
iferr!=nil {
105-
returnxerrors.New("That's not a valid email address!")
106-
}
77+
ifusername=="" {
78+
if!isTTY(cmd) {
79+
returnxerrors.New("the initial user cannot be created in non-interactive mode. use the API")
80+
}
81+
_,err:=cliui.Prompt(cmd, cliui.PromptOptions{
82+
Text:"Would you like to create the first user?",
83+
Default:"yes",
84+
IsConfirm:true,
85+
})
86+
iferrors.Is(err,cliui.Canceled) {
87+
returnnil
88+
}
89+
iferr!=nil {
10790
returnerr
108-
},
109-
})
110-
iferr!=nil {
111-
returnxerrors.Errorf("specify email prompt: %w",err)
91+
}
92+
currentUser,err:=user.Current()
93+
iferr!=nil {
94+
returnxerrors.Errorf("get current user: %w",err)
95+
}
96+
username,err=cliui.Prompt(cmd, cliui.PromptOptions{
97+
Text:"What "+cliui.Styles.Field.Render("username")+" would you like?",
98+
Default:currentUser.Username,
99+
})
100+
iferrors.Is(err,cliui.Canceled) {
101+
returnnil
102+
}
103+
iferr!=nil {
104+
returnxerrors.Errorf("pick username prompt: %w",err)
105+
}
112106
}
113107

114-
password,err:=cliui.Prompt(cmd, cliui.PromptOptions{
115-
Text:"Enter a "+cliui.Styles.Field.Render("password")+":",
116-
Secret:true,
117-
Validate:cliui.ValidateNotEmpty,
118-
})
119-
iferr!=nil {
120-
returnxerrors.Errorf("specify password prompt: %w",err)
108+
ifemail=="" {
109+
email,err=cliui.Prompt(cmd, cliui.PromptOptions{
110+
Text:"What's your "+cliui.Styles.Field.Render("email")+"?",
111+
Validate:func(sstring)error {
112+
err:=validator.New().Var(s,"email")
113+
iferr!=nil {
114+
returnxerrors.New("That's not a valid email address!")
115+
}
116+
returnerr
117+
},
118+
})
119+
iferr!=nil {
120+
returnxerrors.Errorf("specify email prompt: %w",err)
121+
}
121122
}
122-
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
123-
Text:"Confirm "+cliui.Styles.Field.Render("password")+":",
124-
Secret:true,
125-
Validate:func(sstring)error {
126-
ifs!=password {
127-
returnxerrors.Errorf("Passwords do not match")
128-
}
129-
returnnil
130-
},
131-
})
132-
iferr!=nil {
133-
returnxerrors.Errorf("confirm password prompt: %w",err)
123+
124+
ifpassword=="" {
125+
password,err=cliui.Prompt(cmd, cliui.PromptOptions{
126+
Text:"Enter a "+cliui.Styles.Field.Render("password")+":",
127+
Secret:true,
128+
Validate:cliui.ValidateNotEmpty,
129+
})
130+
iferr!=nil {
131+
returnxerrors.Errorf("specify password prompt: %w",err)
132+
}
133+
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
134+
Text:"Confirm "+cliui.Styles.Field.Render("password")+":",
135+
Secret:true,
136+
Validate:func(sstring)error {
137+
ifs!=password {
138+
returnxerrors.Errorf("Passwords do not match")
139+
}
140+
returnnil
141+
},
142+
})
143+
iferr!=nil {
144+
returnxerrors.Errorf("confirm password prompt: %w",err)
145+
}
134146
}
135147

136148
_,err=client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{
@@ -219,6 +231,10 @@ func login() *cobra.Command {
219231
returnnil
220232
},
221233
}
234+
cliflag.StringVarP(cmd.Flags(),&email,"email","e","CODER_EMAIL","","Specifies an email address to authenticate with.")
235+
cliflag.StringVarP(cmd.Flags(),&username,"username","u","CODER_USERNAME","","Specifies a username to authenticate with.")
236+
cliflag.StringVarP(cmd.Flags(),&password,"password","p","CODER_PASSWORD","","Specifies a password to authenticate with.")
237+
returncmd
222238
}
223239

224240
// isWSL determines if coder-cli is running within Windows Subsystem for Linux

‎cli/login_test.go‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ func TestLogin(t *testing.T) {
5656
<-doneChan
5757
})
5858

59+
t.Run("InitialUserFlags",func(t*testing.T) {
60+
t.Parallel()
61+
client:=coderdtest.New(t,nil)
62+
// The --force-tty flag is required on Windows, because the `isatty` library does not
63+
// accurately detect Windows ptys when they are not attached to a process:
64+
// https://github.com/mattn/go-isatty/issues/59
65+
doneChan:=make(chanstruct{})
66+
root,_:=clitest.New(t,"login",client.URL.String(),"--username","testuser","--email","user@coder.com","--password","password")
67+
pty:=ptytest.New(t)
68+
root.SetIn(pty.Input())
69+
root.SetOut(pty.Output())
70+
gofunc() {
71+
deferclose(doneChan)
72+
err:=root.Execute()
73+
assert.NoError(t,err)
74+
}()
75+
pty.ExpectMatch("Welcome to Coder")
76+
<-doneChan
77+
})
78+
5979
t.Run("InitialUserTTYConfirmPasswordFailAndReprompt",func(t*testing.T) {
6080
t.Parallel()
6181
ctx,cancel:=context.WithCancel(context.Background())

‎cli/root.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ func Root() *cobra.Command {
5757
SilenceUsage:true,
5858
Long:`Coder — A tool for provisioning self-hosted development environments.
5959
`,
60-
Example:` StartCoder in "dev" mode. This dev-mode requires no further setup, and your local `+cliui.Styles.Code.Render("coder")+` CLI will be authenticated to talk to it. This makes it easy to experiment withCoder.
61-
`+cliui.Styles.Code.Render("$ coder server --dev")+`
60+
Example:` StartaCoder server.
61+
`+cliui.Styles.Code.Render("$ coder server")+`
6262
6363
Get started by creating a template from an example.
6464
`+cliui.Styles.Code.Render("$ coder templates init"),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp