Skip to content

Commit 95b9a14

Browse files
committed
Merge remote-tracking branch 'origin/main' into stevenmasley/list_roles
2 parents d083a7c + e530ab2 commit 95b9a14

37 files changed

+1171
-232
lines changed

.github/workflows/coder.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ jobs:
9999
with:
100100
go-version: "~1.18"
101101
- run: curl -sSL
102-
https://github.com/kyleconroy/sqlc/releases/download/v1.11.0/sqlc_1.11.0_linux_amd64.tar.gz
102+
https://github.com/kyleconroy/sqlc/releases/download/v1.13.0/sqlc_1.13.0_linux_amd64.tar.gz
103103
| sudo tar -C /usr/bin -xz sqlc
104104

105105
- run: go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
@@ -354,8 +354,14 @@ jobs:
354354
restore-keys: |
355355
js-${{ runner.os }}-
356356
357+
- name: Build site
358+
run: make site/out
359+
357360
- name: Build Release
358-
run: make release
361+
uses: goreleaser/goreleaser-action@v2.9.1
362+
with:
363+
version: latest
364+
args: release --snapshot --rm-dist --skip-sign
359365

360366
- uses: actions/upload-artifact@v3
361367
with:

Makefile

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
1+
.DEFAULT_GOAL := build
2+
13
INSTALL_DIR=$(shell go env GOPATH)/bin
24
GOOS=$(shell go env GOOS)
35
GOARCH=$(shell go env GOARCH)
46

5-
bin:
6-
goreleaser build --snapshot --rm-dist
7-
.PHONY: bin
7+
bin: $(shell find -not -path './vendor/*' -type f -name '*.go') go.mod go.sum
8+
@echo "== This builds binaries for command-line usage."
9+
@echo "== Use \"make build\" to embed the site."
10+
goreleaser build --snapshot --rm-dist --single-target
811

9-
build: site/out bin
12+
build: dist/artifacts.json
1013
.PHONY: build
1114

1215
# Runs migrations to output a dump of the database.
1316
coderd/database/dump.sql: $(wildcard coderd/database/migrations/*.sql)
1417
go run coderd/database/dump/main.go
15-
.PHONY: coderd/database/dump.sql
1618

1719
# Generates Go code for querying the database.
18-
coderd/database/generate: coderd/database/dump.sql $(wildcard coderd/database/queries/*.sql)
20+
coderd/database/querier.go: coderd/database/dump.sql $(wildcard coderd/database/queries/*.sql)
1921
coderd/database/generate.sh
20-
.PHONY: coderd/database/generate
2122

22-
apitypings/generate: site/src/api/types.ts
23-
go run scripts/apitypings/main.go > site/src/api/typesGenerated.ts
24-
cd site && yarn run format:types
25-
.PHONY: apitypings/generate
23+
dist/artifacts.json: site/out $(shell find -not -path './vendor/*' -type f -name '*.go') go.mod go.sum
24+
goreleaser release --snapshot --rm-dist --skip-sign
2625

2726
fmt/prettier:
2827
@echo "--- prettier"
@@ -36,12 +35,12 @@ endif
3635

3736
fmt/terraform: $(wildcard *.tf)
3837
terraform fmt -recursive
38+
.PHONY: fmt/terraform
3939

4040
fmt: fmt/prettier fmt/terraform
4141
.PHONY: fmt
4242

43-
gen: coderd/database/generate peerbroker/proto provisionersdk/proto provisionerd/proto apitypings/generate
44-
.PHONY: gen
43+
gen: coderd/database/querier.go peerbroker/proto/peerbroker.pb.go provisionersdk/proto/provisioner.pb.go provisionerd/proto/provisionerd.pb.go site/src/api/typesGenerated.ts
4544

4645
install: build
4746
@echo "--- Copying from bin to $(INSTALL_DIR)"
@@ -53,44 +52,40 @@ lint:
5352
golangci-lint run
5453
.PHONY: lint
5554

56-
peerbroker/proto: peerbroker/proto/peerbroker.proto
55+
peerbroker/proto/peerbroker.pb.go: peerbroker/proto/peerbroker.proto
5756
protoc \
5857
--go_out=. \
5958
--go_opt=paths=source_relative \
6059
--go-drpc_out=. \
6160
--go-drpc_opt=paths=source_relative \
6261
./peerbroker/proto/peerbroker.proto
63-
.PHONY: peerbroker/proto
6462

65-
provisionerd/proto: provisionerd/proto/provisionerd.proto
63+
provisionerd/proto/provisionerd.pb.go: provisionerd/proto/provisionerd.proto
6664
protoc \
6765
--go_out=. \
6866
--go_opt=paths=source_relative \
6967
--go-drpc_out=. \
7068
--go-drpc_opt=paths=source_relative \
7169
./provisionerd/proto/provisionerd.proto
72-
.PHONY: provisionerd/proto
7370

74-
provisionersdk/proto: provisionersdk/proto/provisioner.proto
71+
provisionersdk/proto/provisioner.pb.go: provisionersdk/proto/provisioner.proto
7572
protoc \
7673
--go_out=. \
7774
--go_opt=paths=source_relative \
7875
--go-drpc_out=. \
7976
--go-drpc_opt=paths=source_relative \
8077
./provisionersdk/proto/provisioner.proto
81-
.PHONY: provisionersdk/proto
8278

83-
release: site/out
84-
goreleaser release --snapshot --rm-dist --skip-sign
85-
.PHONY: release
86-
87-
site/out:
79+
site/out: $(shell find ./site -not -path './site/node_modules/*' -type f -name '*.tsx') $(shell find ./site -not -path './site/node_modules/*' -type f -name '*.ts') site/package.json
8880
./scripts/yarn_install.sh
8981
cd site && yarn typegen
9082
cd site && yarn build
9183
# Restores GITKEEP files!
9284
git checkout HEAD site/out
93-
.PHONY: site/out
85+
86+
site/src/api/typesGenerated.ts: $(shell find codersdk -type f -name '*.go')
87+
go run scripts/apitypings/main.go > site/src/api/typesGenerated.ts
88+
cd site && yarn run format:types
9489

9590
test:
9691
gotestsum -- -v -short ./...

agent/agent.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,9 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, rawID string, conn ne
518518
break
519519
}
520520
part := buffer[:read]
521+
rpty.circularBufferMutex.Lock()
521522
_, err = rpty.circularBuffer.Write(part)
523+
rpty.circularBufferMutex.Unlock()
522524
if err != nil {
523525
a.logger.Error(ctx, "reconnecting pty write buffer", slog.Error(err), slog.F("id", id))
524526
break
@@ -545,7 +547,9 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, rawID string, conn ne
545547
a.logger.Error(ctx, "resize reconnecting pty", slog.F("id", id), slog.Error(err))
546548
}
547549
// Write any previously stored data for the TTY.
550+
rpty.circularBufferMutex.RLock()
548551
_, err = conn.Write(rpty.circularBuffer.Bytes())
552+
rpty.circularBufferMutex.RUnlock()
549553
if err != nil {
550554
a.logger.Warn(ctx, "write reconnecting pty buffer", slog.F("id", id), slog.Error(err))
551555
return
@@ -640,9 +644,10 @@ type reconnectingPTY struct {
640644
activeConnsMutex sync.Mutex
641645
activeConns map[string]net.Conn
642646

643-
circularBuffer *circbuf.Buffer
644-
timeout *time.Timer
645-
ptty pty.PTY
647+
circularBuffer *circbuf.Buffer
648+
circularBufferMutex sync.RWMutex
649+
timeout *time.Timer
650+
ptty pty.PTY
646651
}
647652

648653
// Close ends all connections to the reconnecting

cli/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func Root() *cobra.Command {
8080
server(),
8181
show(),
8282
start(),
83+
state(),
8384
stop(),
8485
ssh(),
8586
templates(),

cli/server.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"log"
1313
"net"
1414
"net/http"
15+
"net/http/pprof"
1516
"net/url"
1617
"os"
1718
"os/signal"
@@ -23,6 +24,7 @@ import (
2324
"github.com/google/go-github/v43/github"
2425
"github.com/pion/turn/v2"
2526
"github.com/pion/webrtc/v3"
27+
"github.com/prometheus/client_golang/prometheus/promhttp"
2628
"github.com/spf13/cobra"
2729
"golang.org/x/oauth2"
2830
xgithub "golang.org/x/oauth2/github"
@@ -55,6 +57,10 @@ func server() *cobra.Command {
5557
var (
5658
accessURL string
5759
address string
60+
promEnabled bool
61+
promAddress string
62+
pprofEnabled bool
63+
pprofAddress string
5864
cacheDir string
5965
dev bool
6066
devUserEmail string
@@ -245,6 +251,17 @@ func server() *cobra.Command {
245251
}
246252
}
247253

254+
// This prevents the pprof import from being accidentally deleted.
255+
var _ = pprof.Handler
256+
if pprofEnabled {
257+
//nolint:revive
258+
defer serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof")()
259+
}
260+
if promEnabled {
261+
//nolint:revive
262+
defer serveHandler(cmd.Context(), logger, promhttp.Handler(), promAddress, "prometheus")()
263+
}
264+
248265
errCh := make(chan error, 1)
249266
provisionerDaemons := make([]*provisionerd.Server, 0)
250267
for i := 0; uint8(i) < provisionerDaemonCount; i++ {
@@ -400,8 +417,12 @@ func server() *cobra.Command {
400417
},
401418
}
402419

403-
cliflag.StringVarP(root.Flags(), &accessURL, "access-url", "", "CODER_ACCESS_URL", "", "Specifies the external URL to access Coder")
404-
cliflag.StringVarP(root.Flags(), &address, "address", "a", "CODER_ADDRESS", "127.0.0.1:3000", "The address to serve the API and dashboard")
420+
cliflag.StringVarP(root.Flags(), &accessURL, "access-url", "", "CODER_ACCESS_URL", "", "Specifies the external URL to access Coder.")
421+
cliflag.StringVarP(root.Flags(), &address, "address", "a", "CODER_ADDRESS", "127.0.0.1:3000", "The address to serve the API and dashboard.")
422+
cliflag.BoolVarP(root.Flags(), &promEnabled, "prometheus-enable", "", "CODER_PROMETHEUS_ENABLE", false, "Enable serving prometheus metrics on the addressdefined by --prometheus-address.")
423+
cliflag.StringVarP(root.Flags(), &promAddress, "prometheus-address", "", "CODER_PROMETHEUS_ADDRESS", "127.0.0.1:2112", "The address to serve prometheus metrics.")
424+
cliflag.BoolVarP(root.Flags(), &promEnabled, "pprof-enable", "", "CODER_PPROF_ENABLE", false, "Enable serving pprof metrics on the address defined by --pprof-address.")
425+
cliflag.StringVarP(root.Flags(), &pprofAddress, "pprof-address", "", "CODER_PPROF_ADDRESS", "127.0.0.1:6060", "The address to serve pprof.")
405426
// systemd uses the CACHE_DIRECTORY environment variable!
406427
cliflag.StringVarP(root.Flags(), &cacheDir, "cache-dir", "", "CACHE_DIRECTORY", filepath.Join(os.TempDir(), "coder-cache"), "Specifies a directory to cache binaries for provision operations.")
407428
cliflag.BoolVarP(root.Flags(), &dev, "dev", "", "CODER_DEV_MODE", false, "Serve Coder in dev mode for tinkering")
@@ -661,6 +682,20 @@ func configureGithubOAuth2(accessURL *url.URL, clientID, clientSecret string, al
661682
}, nil
662683
}
663684

685+
func serveHandler(ctx context.Context, logger slog.Logger, handler http.Handler, addr, name string) (closeFunc func()) {
686+
logger.Debug(ctx, "http server listening", slog.F("addr", addr), slog.F("name", name))
687+
688+
srv := &http.Server{Addr: addr, Handler: handler}
689+
go func() {
690+
err := srv.ListenAndServe()
691+
if err != nil && !xerrors.Is(err, http.ErrServerClosed) {
692+
logger.Error(ctx, "http server listen", slog.F("name", name), slog.Error(err))
693+
}
694+
}()
695+
696+
return func() { _ = srv.Close() }
697+
}
698+
664699
type datadogLogger struct {
665700
logger slog.Logger
666701
}

cli/state.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package cli
2+
3+
import (
4+
"io"
5+
"os"
6+
"time"
7+
8+
"github.com/spf13/cobra"
9+
10+
"github.com/coder/coder/cli/cliui"
11+
"github.com/coder/coder/codersdk"
12+
)
13+
14+
func state() *cobra.Command {
15+
cmd := &cobra.Command{
16+
Use: "state",
17+
}
18+
cmd.AddCommand(statePull(), statePush())
19+
return cmd
20+
}
21+
22+
func statePull() *cobra.Command {
23+
var buildName string
24+
cmd := &cobra.Command{
25+
Use: "pull <workspace> [file]",
26+
Args: cobra.MinimumNArgs(1),
27+
RunE: func(cmd *cobra.Command, args []string) error {
28+
client, err := createClient(cmd)
29+
if err != nil {
30+
return err
31+
}
32+
organization, err := currentOrganization(cmd, client)
33+
if err != nil {
34+
return err
35+
}
36+
37+
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
38+
if err != nil {
39+
return err
40+
}
41+
var build codersdk.WorkspaceBuild
42+
if buildName == "latest" {
43+
build = workspace.LatestBuild
44+
} else {
45+
build, err = client.WorkspaceBuildByName(cmd.Context(), workspace.ID, buildName)
46+
if err != nil {
47+
return err
48+
}
49+
}
50+
51+
state, err := client.WorkspaceBuildState(cmd.Context(), build.ID)
52+
if err != nil {
53+
return err
54+
}
55+
56+
if len(args) < 2 {
57+
cmd.Println(string(state))
58+
return nil
59+
}
60+
61+
return os.WriteFile(args[1], state, 0600)
62+
},
63+
}
64+
cmd.Flags().StringVarP(&buildName, "build", "b", "latest", "Specify a workspace build to target by name.")
65+
return cmd
66+
}
67+
68+
func statePush() *cobra.Command {
69+
var buildName string
70+
cmd := &cobra.Command{
71+
Use: "push <workspace> <file>",
72+
Args: cobra.ExactArgs(2),
73+
RunE: func(cmd *cobra.Command, args []string) error {
74+
client, err := createClient(cmd)
75+
if err != nil {
76+
return err
77+
}
78+
organization, err := currentOrganization(cmd, client)
79+
if err != nil {
80+
return err
81+
}
82+
83+
workspace, err := client.WorkspaceByOwnerAndName(cmd.Context(), organization.ID, codersdk.Me, args[0])
84+
if err != nil {
85+
return err
86+
}
87+
var build codersdk.WorkspaceBuild
88+
if buildName == "latest" {
89+
build = workspace.LatestBuild
90+
} else {
91+
build, err = client.WorkspaceBuildByName(cmd.Context(), workspace.ID, buildName)
92+
if err != nil {
93+
return err
94+
}
95+
}
96+
97+
var state []byte
98+
if args[1] == "-" {
99+
state, err = io.ReadAll(cmd.InOrStdin())
100+
} else {
101+
state, err = os.ReadFile(args[1])
102+
}
103+
if err != nil {
104+
return err
105+
}
106+
107+
before := time.Now()
108+
build, err = client.CreateWorkspaceBuild(cmd.Context(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
109+
TemplateVersionID: build.TemplateVersionID,
110+
Transition: build.Transition,
111+
ProvisionerState: state,
112+
})
113+
if err != nil {
114+
return err
115+
}
116+
return cliui.WorkspaceBuild(cmd.Context(), cmd.OutOrStderr(), client, build.ID, before)
117+
},
118+
}
119+
cmd.Flags().StringVarP(&buildName, "build", "b", "latest", "Specify a workspace build to target by name.")
120+
return cmd
121+
}

0 commit comments

Comments
 (0)