Skip to content

Commit c07e571

Browse files
committed
Merge branch 'main' into light-theme
2 parents 6314341 + 24080b1 commit c07e571

File tree

64 files changed

+1230
-829
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1230
-829
lines changed

.github/workflows/release.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,29 @@ jobs:
479479
# For gh CLI. We need a real token since we're commenting on a PR in a
480480
# different repo.
481481
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
482+
483+
# publish-sqlc pushes the latest schema to sqlc cloud.
484+
# At present these pushes cannot be tagged, so the last push is always the latest.
485+
publish-sqlc:
486+
name: "Publish to schema sqlc cloud"
487+
runs-on: "ubuntu-latest"
488+
needs: release
489+
if: ${{ !inputs.dry_run }}
490+
steps:
491+
- name: Checkout
492+
uses: actions/checkout@v4
493+
with:
494+
fetch-depth: 1
495+
496+
# We need golang to run the migration main.go
497+
- name: Setup Go
498+
uses: ./.github/actions/setup-go
499+
500+
- name: Setup sqlc
501+
uses: ./.github/actions/setup-sqlc
502+
503+
- name: Push schema to sqlc cloud
504+
# Don't block a release on this
505+
continue-on-error: true
506+
run: |
507+
make sqlc-push

Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,27 @@ test:
708708
gotestsum --format standard-quiet -- -v -short -count=1 ./...
709709
.PHONY: test
710710

711+
# sqlc-cloud-is-setup will fail if no SQLc auth token is set. Use this as a
712+
# dependency for any sqlc-cloud related targets.
713+
sqlc-cloud-is-setup:
714+
if [[ "$(SQLC_AUTH_TOKEN)" == "" ]]; then
715+
echo "ERROR: 'SQLC_AUTH_TOKEN' must be set to auth with sqlc cloud before running verify." 1>&2
716+
exit 1
717+
fi
718+
.PHONY: sqlc-cloud-is-setup
719+
720+
sqlc-push: sqlc-cloud-is-setup test-postgres-docker
721+
echo "--- sqlc push"
722+
SQLC_DATABASE_URL="postgresql://postgres:postgres@localhost:5432/$(shell go run scripts/migrate-ci/main.go)" \
723+
sqlc push -f coderd/database/sqlc.yaml && echo "Passed sqlc push"
724+
.PHONY: sqlc-push
725+
726+
sqlc-verify: sqlc-cloud-is-setup test-postgres-docker
727+
echo "--- sqlc verify"
728+
SQLC_DATABASE_URL="postgresql://postgres:postgres@localhost:5432/$(shell go run scripts/migrate-ci/main.go)" \
729+
sqlc verify -f coderd/database/sqlc.yaml && echo "Passed sqlc verify"
730+
.PHONY: sqlc-verify
731+
711732
sqlc-vet: test-postgres-docker
712733
echo "--- sqlc vet"
713734
SQLC_DATABASE_URL="postgresql://postgres:postgres@localhost:5432/$(shell go run scripts/migrate-ci/main.go)" \

agent/agentscripts/agentscripts.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ func (r *Runner) StartCron() {
135135
// So if we are closed, we just return, and skip the Run() entirely.
136136
select {
137137
case <-r.cronCtx.Done():
138-
// The cronCtx is cancelled before cron.Close() happens. So if the ctx is
139-
// cancelled, then Close() will be called, or it is about to be called.
138+
// The cronCtx is canceled before cron.Close() happens. So if the ctx is
139+
// canceled, then Close() will be called, or it is about to be called.
140140
// So do nothing!
141141
default:
142142
r.cron.Run()

cli/clilog/clilog.go

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
package clilog
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"os"
8+
"regexp"
9+
"strings"
10+
11+
"golang.org/x/xerrors"
12+
13+
"cdr.dev/slog"
14+
"cdr.dev/slog/sloggers/sloghuman"
15+
"cdr.dev/slog/sloggers/slogjson"
16+
"cdr.dev/slog/sloggers/slogstackdriver"
17+
"github.com/coder/coder/v2/cli/clibase"
18+
"github.com/coder/coder/v2/coderd/tracing"
19+
"github.com/coder/coder/v2/codersdk"
20+
)
21+
22+
type (
23+
Option func(*Builder)
24+
Builder struct {
25+
Filter []string
26+
Human string
27+
JSON string
28+
Stackdriver string
29+
Trace bool
30+
Verbose bool
31+
}
32+
)
33+
34+
func New(opts ...Option) *Builder {
35+
b := &Builder{}
36+
for _, opt := range opts {
37+
opt(b)
38+
}
39+
return b
40+
}
41+
42+
func WithFilter(filters ...string) Option {
43+
return func(b *Builder) {
44+
b.Filter = filters
45+
}
46+
}
47+
48+
func WithHuman(loc string) Option {
49+
return func(b *Builder) {
50+
b.Human = loc
51+
}
52+
}
53+
54+
func WithJSON(loc string) Option {
55+
return func(b *Builder) {
56+
b.JSON = loc
57+
}
58+
}
59+
60+
func WithStackdriver(loc string) Option {
61+
return func(b *Builder) {
62+
b.Stackdriver = loc
63+
}
64+
}
65+
66+
func WithTrace() Option {
67+
return func(b *Builder) {
68+
b.Trace = true
69+
}
70+
}
71+
72+
func WithVerbose() Option {
73+
return func(b *Builder) {
74+
b.Verbose = true
75+
}
76+
}
77+
78+
func FromDeploymentValues(vals *codersdk.DeploymentValues) Option {
79+
return func(b *Builder) {
80+
b.Filter = vals.Logging.Filter.Value()
81+
b.Human = vals.Logging.Human.Value()
82+
b.JSON = vals.Logging.JSON.Value()
83+
b.Stackdriver = vals.Logging.Stackdriver.Value()
84+
b.Trace = vals.Trace.Enable.Value()
85+
b.Verbose = vals.Verbose.Value()
86+
}
87+
}
88+
89+
func (b *Builder) Build(inv *clibase.Invocation) (log slog.Logger, closeLog func(), err error) {
90+
var (
91+
sinks = []slog.Sink{}
92+
closers = []func() error{}
93+
)
94+
defer func() {
95+
if err != nil {
96+
for _, closer := range closers {
97+
_ = closer()
98+
}
99+
}
100+
}()
101+
102+
noopClose := func() {}
103+
104+
addSinkIfProvided := func(sinkFn func(io.Writer) slog.Sink, loc string) error {
105+
switch loc {
106+
case "":
107+
108+
case "/dev/stdout":
109+
sinks = append(sinks, sinkFn(inv.Stdout))
110+
111+
case "/dev/stderr":
112+
sinks = append(sinks, sinkFn(inv.Stderr))
113+
114+
default:
115+
fi, err := os.OpenFile(loc, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
116+
if err != nil {
117+
return xerrors.Errorf("open log file %q: %w", loc, err)
118+
}
119+
closers = append(closers, fi.Close)
120+
sinks = append(sinks, sinkFn(fi))
121+
}
122+
return nil
123+
}
124+
125+
err = addSinkIfProvided(sloghuman.Sink, b.Human)
126+
if err != nil {
127+
return slog.Logger{}, noopClose, xerrors.Errorf("add human sink: %w", err)
128+
}
129+
err = addSinkIfProvided(slogjson.Sink, b.JSON)
130+
if err != nil {
131+
return slog.Logger{}, noopClose, xerrors.Errorf("add json sink: %w", err)
132+
}
133+
err = addSinkIfProvided(slogstackdriver.Sink, b.Stackdriver)
134+
if err != nil {
135+
return slog.Logger{}, noopClose, xerrors.Errorf("add stackdriver sink: %w", err)
136+
}
137+
138+
if b.Trace {
139+
sinks = append(sinks, tracing.SlogSink{})
140+
}
141+
142+
// User should log to null device if they don't want logs.
143+
if len(sinks) == 0 {
144+
return slog.Logger{}, noopClose, xerrors.New("no loggers provided, use /dev/null to disable logging")
145+
}
146+
147+
filter := &debugFilterSink{next: sinks}
148+
149+
err = filter.compile(b.Filter)
150+
if err != nil {
151+
return slog.Logger{}, noopClose, xerrors.Errorf("compile filters: %w", err)
152+
}
153+
154+
level := slog.LevelInfo
155+
// Debug logging is always enabled if a filter is present.
156+
if b.Verbose || filter.re != nil {
157+
level = slog.LevelDebug
158+
}
159+
160+
return inv.Logger.AppendSinks(filter).Leveled(level), func() {
161+
for _, closer := range closers {
162+
_ = closer()
163+
}
164+
}, nil
165+
}
166+
167+
var _ slog.Sink = &debugFilterSink{}
168+
169+
type debugFilterSink struct {
170+
next []slog.Sink
171+
re *regexp.Regexp
172+
}
173+
174+
func (f *debugFilterSink) compile(res []string) error {
175+
if len(res) == 0 {
176+
return nil
177+
}
178+
179+
var reb strings.Builder
180+
for i, re := range res {
181+
_, _ = fmt.Fprintf(&reb, "(%s)", re)
182+
if i != len(res)-1 {
183+
_, _ = reb.WriteRune('|')
184+
}
185+
}
186+
187+
re, err := regexp.Compile(reb.String())
188+
if err != nil {
189+
return xerrors.Errorf("compile regex: %w", err)
190+
}
191+
f.re = re
192+
return nil
193+
}
194+
195+
func (f *debugFilterSink) LogEntry(ctx context.Context, ent slog.SinkEntry) {
196+
if ent.Level == slog.LevelDebug {
197+
logName := strings.Join(ent.LoggerNames, ".")
198+
if f.re != nil && !f.re.MatchString(logName) && !f.re.MatchString(ent.Message) {
199+
return
200+
}
201+
}
202+
for _, sink := range f.next {
203+
sink.LogEntry(ctx, ent)
204+
}
205+
}
206+
207+
func (f *debugFilterSink) Sync() {
208+
for _, sink := range f.next {
209+
sink.Sync()
210+
}
211+
}

0 commit comments

Comments
 (0)