Skip to content

Commit 047ca3b

Browse files
committed
Merge remote-tracking branch 'origin/main' into 13207-preinstall-jetbrains
* origin/main: (31 commits) docs: document issue with direnv and nix-shell on macOS (#15990) (#16015) chore: add spinner component (#16014) chore: bump react-syntax-highlighter from 15.5.0 to 15.6.1 in /site (#16003) chore: bump @radix-ui/react-dialog from 1.1.2 to 1.1.4 in /site (#15999) chore(provisionerd): close completeChan exactly once (#16011) fix(examples): add keep_locally to docker_image resources (#16012) feat: notify on workspace update (#15979) chore(apiversion): add guidelines regarding bumping apiversion (#16009) docs: add note about TLD and wildcards (#16008) chore: bump @storybook/preview-api from 8.4.6 to 8.4.7 in /site (#16002) ci: make sure golden files are actually up to date (#15989) chore: bump eslint-config-next from 14.2.18 to 14.2.22 in /offlinedocs (#15996) chore: bump @types/node from 20.17.6 to 20.17.11 in /site (#16001) chore: bump @types/node from 20.17.9 to 20.17.11 in /offlinedocs (#15995) chore: bump next from 14.2.16 to 14.2.22 in /offlinedocs (#15993) chore: bump the mui group across 1 directory with 6 updates (#15991) fix(enterprise/cli): add missing defer close of closer funcs (#15986) fix(cli/cliui): handle typed nil and null time in tables (#15984) test: fix incorrectly placed cleanup defer in dbtestutil (#15987) chore(scripts): remove unused ci-report (#15988) ...
2 parents 75875f3 + 761a196 commit 047ca3b

File tree

4,147 files changed

+2133
-5956
lines changed

Some content is hidden

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

4,147 files changed

+2133
-5956
lines changed

.github/workflows/ci.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,15 @@ jobs:
271271
# coderd/rbac/object_gen.go:1:1: syntax error: package statement must be first
272272
run: "make --output-sync -B gen"
273273

274+
- name: make update-golden-files
275+
run: |
276+
make clean/golden-files
277+
# Notifications require DB, we could start a DB instance here but
278+
# let's just restore for now.
279+
git checkout -- coderd/notifications/testdata/rendered-templates
280+
# As above, skip `-j` flag.
281+
make --output-sync -B update-golden-files
282+
274283
- name: Check for unstaged files
275284
run: ./scripts/check_unstaged.sh
276285

.github/workflows/typos.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ extend-exclude = [
3535
# These files contain base64 strings that confuse the detector
3636
"**XService**.ts",
3737
"**identity.go",
38-
"scripts/ci-report/testdata/**",
3938
"**/*_test.go",
4039
"**/*.test.tsx",
4140
"**/pnpm-lock.yaml",

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://coder.com/docs/CONTRIBUTING

Makefile

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,9 @@ fmt/go:
422422
echo "$(GREEN)==>$(RESET) $(BOLD)fmt/go$(RESET)"
423423
# VS Code users should check out
424424
# https://github.com/mvdan/gofumpt#visual-studio-code
425-
go run mvdan.cc/[email protected] -w -l .
425+
find . $(FIND_EXCLUSIONS) -type f -name '*.go' -print0 | \
426+
xargs -0 grep --null -L "DO NOT EDIT" | \
427+
xargs -0 go run mvdan.cc/[email protected] -w -l
426428
.PHONY: fmt/go
427429

428430
fmt/ts:
@@ -511,9 +513,7 @@ TAILNETTEST_MOCKS := \
511513
tailnet/tailnettest/workspaceupdatesprovidermock.go \
512514
tailnet/tailnettest/subscriptionmock.go
513515

514-
515-
# all gen targets should be added here and to gen/mark-fresh
516-
gen: \
516+
GEN_FILES := \
517517
tailnet/proto/tailnet.pb.go \
518518
agent/proto/agent.pb.go \
519519
provisionersdk/proto/provisioner.pb.go \
@@ -538,8 +538,14 @@ gen: \
538538
examples/examples.gen.json \
539539
$(TAILNETTEST_MOCKS) \
540540
coderd/database/pubsub/psmock/psmock.go
541+
542+
# all gen targets should be added here and to gen/mark-fresh
543+
gen: $(GEN_FILES)
541544
.PHONY: gen
542545

546+
gen/db: $(DB_GEN_FILES)
547+
.PHONY: gen/db
548+
543549
# Mark all generated files as fresh so make thinks they're up-to-date. This is
544550
# used during releases so we don't run generation scripts.
545551
gen/mark-fresh:
@@ -696,19 +702,33 @@ coderd/apidoc/swagger.json: $(shell find ./scripts/apidocgen $(FIND_EXCLUSIONS)
696702

697703
update-golden-files: \
698704
cli/testdata/.gen-golden \
699-
helm/coder/tests/testdata/.gen-golden \
700-
helm/provisioner/tests/testdata/.gen-golden \
701-
scripts/ci-report/testdata/.gen-golden \
702-
enterprise/cli/testdata/.gen-golden \
703-
enterprise/tailnet/testdata/.gen-golden \
704-
tailnet/testdata/.gen-golden \
705705
coderd/.gen-golden \
706706
coderd/notifications/.gen-golden \
707-
provisioner/terraform/testdata/.gen-golden
707+
enterprise/cli/testdata/.gen-golden \
708+
enterprise/tailnet/testdata/.gen-golden \
709+
helm/coder/tests/testdata/.gen-golden \
710+
helm/provisioner/tests/testdata/.gen-golden \
711+
provisioner/terraform/testdata/.gen-golden \
712+
tailnet/testdata/.gen-golden
708713
.PHONY: update-golden-files
709714

715+
clean/golden-files:
716+
find . -type f -name '.gen-golden' -delete
717+
find \
718+
cli/testdata \
719+
coderd/notifications/testdata \
720+
coderd/testdata \
721+
enterprise/cli/testdata \
722+
enterprise/tailnet/testdata \
723+
helm/coder/tests/testdata \
724+
helm/provisioner/tests/testdata \
725+
provisioner/terraform/testdata \
726+
tailnet/testdata \
727+
-type f -name '*.golden' -delete
728+
.PHONY: clean/golden-files
729+
710730
cli/testdata/.gen-golden: $(wildcard cli/testdata/*.golden) $(wildcard cli/*.tpl) $(GO_SRC_FILES) $(wildcard cli/*_test.go)
711-
go test ./cli -run="Test(CommandHelp|ServerYAML|ErrorExamples)" -update
731+
go test ./cli -run="Test(CommandHelp|ServerYAML|ErrorExamples|.*Golden)" -update
712732
touch "$@"
713733

714734
enterprise/cli/testdata/.gen-golden: $(wildcard enterprise/cli/testdata/*.golden) $(wildcard cli/*.tpl) $(GO_SRC_FILES) $(wildcard enterprise/cli/*_test.go)
@@ -749,10 +769,6 @@ provisioner/terraform/testdata/version:
749769
fi
750770
.PHONY: provisioner/terraform/testdata/version
751771

752-
scripts/ci-report/testdata/.gen-golden: $(wildcard scripts/ci-report/testdata/*) $(wildcard scripts/ci-report/*.go)
753-
go test ./scripts/ci-report -run=TestOutputMatchesGoldenFile -update
754-
touch "$@"
755-
756772
# Combine .gitignore with .prettierignore.include to generate .prettierignore.
757773
.prettierignore: .gitignore .prettierignore.include
758774
echo "# Code generated by Makefile ($^). DO NOT EDIT." > "$@"

apiversion/doc.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Package apiversion provides an API version type that can be used to validate
2+
// compatibility between two API versions.
3+
//
4+
// NOTE: API VERSIONS ARE NOT SEMANTIC VERSIONS.
5+
//
6+
// API versions are represented as major.minor where major and minor are both
7+
// positive integers.
8+
//
9+
// API versions are not directly tied to a specific release of the software.
10+
// Instead, they are used to represent the capabilities of the server. For
11+
// example, a server that supports API version 1.2 should be able to handle
12+
// requests from clients that support API version 1.0, 1.1, or 1.2.
13+
// However, a server that supports API version 2.0 is not required to handle
14+
// requests from clients that support API version 1.x.
15+
// Clients may need to negotiate with the server to determine the highest
16+
// supported API version.
17+
//
18+
// When making a change to the API, use the following rules to determine the
19+
// next API version:
20+
// 1. If the change is backward-compatible, increment the minor version.
21+
// Examples of backward-compatible changes include adding new fields to
22+
// a response or adding new endpoints.
23+
// 2. If the change is not backward-compatible, increment the major version.
24+
// Examples of non-backward-compatible changes include removing or renaming
25+
// fields.
26+
package apiversion

cli/cliui/select.go

Lines changed: 132 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,10 @@ func (m selectModel) filteredOptions() []string {
300300
}
301301

302302
type MultiSelectOptions struct {
303-
Message string
304-
Options []string
305-
Defaults []string
303+
Message string
304+
Options []string
305+
Defaults []string
306+
EnableCustomInput bool
306307
}
307308

308309
func MultiSelect(inv *serpent.Invocation, opts MultiSelectOptions) ([]string, error) {
@@ -328,9 +329,10 @@ func MultiSelect(inv *serpent.Invocation, opts MultiSelectOptions) ([]string, er
328329
}
329330

330331
initialModel := multiSelectModel{
331-
search: textinput.New(),
332-
options: options,
333-
message: opts.Message,
332+
search: textinput.New(),
333+
options: options,
334+
message: opts.Message,
335+
enableCustomInput: opts.EnableCustomInput,
334336
}
335337

336338
initialModel.search.Prompt = ""
@@ -370,12 +372,15 @@ type multiSelectOption struct {
370372
}
371373

372374
type multiSelectModel struct {
373-
search textinput.Model
374-
options []*multiSelectOption
375-
cursor int
376-
message string
377-
canceled bool
378-
selected bool
375+
search textinput.Model
376+
options []*multiSelectOption
377+
cursor int
378+
message string
379+
canceled bool
380+
selected bool
381+
isCustomInputMode bool // track if we're adding a custom option
382+
customInput string // store custom input
383+
enableCustomInput bool // control whether custom input is allowed
379384
}
380385

381386
func (multiSelectModel) Init() tea.Cmd {
@@ -386,6 +391,10 @@ func (multiSelectModel) Init() tea.Cmd {
386391
func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
387392
var cmd tea.Cmd
388393

394+
if m.isCustomInputMode {
395+
return m.handleCustomInputMode(msg)
396+
}
397+
389398
switch msg := msg.(type) {
390399
case terminateMsg:
391400
m.canceled = true
@@ -398,6 +407,11 @@ func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
398407
return m, tea.Quit
399408

400409
case tea.KeyEnter:
410+
// Switch to custom input mode if we're on the "+ Add custom value:" option
411+
if m.enableCustomInput && m.cursor == len(m.filteredOptions()) {
412+
m.isCustomInputMode = true
413+
return m, nil
414+
}
401415
if len(m.options) != 0 {
402416
m.selected = true
403417
return m, tea.Quit
@@ -413,16 +427,16 @@ func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
413427
return m, nil
414428

415429
case tea.KeyUp:
416-
options := m.filteredOptions()
430+
maxIndex := m.getMaxIndex()
417431
if m.cursor > 0 {
418432
m.cursor--
419433
} else {
420-
m.cursor = len(options) - 1
434+
m.cursor = maxIndex
421435
}
422436

423437
case tea.KeyDown:
424-
options := m.filteredOptions()
425-
if m.cursor < len(options)-1 {
438+
maxIndex := m.getMaxIndex()
439+
if m.cursor < maxIndex {
426440
m.cursor++
427441
} else {
428442
m.cursor = 0
@@ -457,6 +471,91 @@ func (m multiSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
457471
return m, cmd
458472
}
459473

474+
func (m multiSelectModel) getMaxIndex() int {
475+
options := m.filteredOptions()
476+
if m.enableCustomInput {
477+
// Include the "+ Add custom value" entry
478+
return len(options)
479+
}
480+
// Includes only the actual options
481+
return len(options) - 1
482+
}
483+
484+
// handleCustomInputMode manages keyboard interactions when in custom input mode
485+
func (m *multiSelectModel) handleCustomInputMode(msg tea.Msg) (tea.Model, tea.Cmd) {
486+
keyMsg, ok := msg.(tea.KeyMsg)
487+
if !ok {
488+
return m, nil
489+
}
490+
491+
switch keyMsg.Type {
492+
case tea.KeyEnter:
493+
return m.handleCustomInputSubmission()
494+
495+
case tea.KeyCtrlC:
496+
m.canceled = true
497+
return m, tea.Quit
498+
499+
case tea.KeyBackspace:
500+
return m.handleCustomInputBackspace()
501+
502+
default:
503+
m.customInput += keyMsg.String()
504+
return m, nil
505+
}
506+
}
507+
508+
// handleCustomInputSubmission processes the submission of custom input
509+
func (m *multiSelectModel) handleCustomInputSubmission() (tea.Model, tea.Cmd) {
510+
if m.customInput == "" {
511+
m.isCustomInputMode = false
512+
return m, nil
513+
}
514+
515+
// Clear search to ensure option is visible and cursor points to the new option
516+
m.search.SetValue("")
517+
518+
// Check for duplicates
519+
for i, opt := range m.options {
520+
if opt.option == m.customInput {
521+
// If the option exists but isn't chosen, select it
522+
if !opt.chosen {
523+
opt.chosen = true
524+
}
525+
526+
// Point cursor to the new option
527+
m.cursor = i
528+
529+
// Reset custom input mode to disabled
530+
m.isCustomInputMode = false
531+
m.customInput = ""
532+
return m, nil
533+
}
534+
}
535+
536+
// Add new unique option
537+
m.options = append(m.options, &multiSelectOption{
538+
option: m.customInput,
539+
chosen: true,
540+
})
541+
542+
// Point cursor to the newly added option
543+
m.cursor = len(m.options) - 1
544+
545+
// Reset custom input mode to disabled
546+
m.customInput = ""
547+
m.isCustomInputMode = false
548+
return m, nil
549+
}
550+
551+
// handleCustomInputBackspace handles backspace in custom input mode
552+
func (m *multiSelectModel) handleCustomInputBackspace() (tea.Model, tea.Cmd) {
553+
if len(m.customInput) > 0 {
554+
m.customInput = m.customInput[:len(m.customInput)-1]
555+
}
556+
return m, nil
557+
}
558+
460559
func (m multiSelectModel) View() string {
461560
var s strings.Builder
462561

@@ -469,13 +568,19 @@ func (m multiSelectModel) View() string {
469568
return s.String()
470569
}
471570

571+
if m.isCustomInputMode {
572+
_, _ = s.WriteString(fmt.Sprintf("%s\nEnter custom value: %s\n", msg, m.customInput))
573+
return s.String()
574+
}
575+
472576
_, _ = s.WriteString(fmt.Sprintf(
473577
"%s %s[Use arrows to move, space to select, <right> to all, <left> to none, type to filter]\n",
474578
msg,
475579
m.search.View(),
476580
))
477581

478-
for i, option := range m.filteredOptions() {
582+
options := m.filteredOptions()
583+
for i, option := range options {
479584
cursor := " "
480585
chosen := "[ ]"
481586
o := option.option
@@ -498,6 +603,16 @@ func (m multiSelectModel) View() string {
498603
))
499604
}
500605

606+
if m.enableCustomInput {
607+
// Add the "+ Add custom value" option at the bottom
608+
cursor := " "
609+
text := " + Add custom value"
610+
if m.cursor == len(options) {
611+
cursor = pretty.Sprint(DefaultStyles.Keyword, "> ")
612+
text = pretty.Sprint(DefaultStyles.Keyword, text)
613+
}
614+
_, _ = s.WriteString(fmt.Sprintf("%s%s\n", cursor, text))
615+
}
501616
return s.String()
502617
}
503618

0 commit comments

Comments
 (0)