Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e49f1d1

Browse files
Merge remote-tracking branch 'origin/main' into dk/prebuilds
2 parents 8ecf5a6 + fc921a5 commit e49f1d1

File tree

54 files changed

+1169
-258
lines changed

Some content is hidden

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

54 files changed

+1169
-258
lines changed
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: "Setup Go tools"
2+
description: |
3+
Set up tools for `make gen`, `offlinedocs` and Schmoder CI.
4+
runs:
5+
using: "composite"
6+
steps:
7+
- name: go install tools
8+
shell: bash
9+
run: |
10+
go install google.golang.org/protobuf/cmd/[email protected]
11+
go install storj.io/drpc/cmd/[email protected]
12+
go install golang.org/x/tools/cmd/[email protected]
13+
go install github.com/mikefarah/yq/[email protected]
14+
go install go.uber.org/mock/[email protected]

.github/workflows/ci.yaml

+2-12
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,7 @@ jobs:
249249
uses: ./.github/actions/setup-tf
250250

251251
- name: go install tools
252-
run: |
253-
go install google.golang.org/protobuf/cmd/[email protected]
254-
go install storj.io/drpc/cmd/[email protected]
255-
go install golang.org/x/tools/cmd/[email protected]
256-
go install github.com/mikefarah/yq/[email protected]
257-
go install go.uber.org/mock/[email protected]
252+
uses: ./.github/actions/setup-go-tools
258253

259254
- name: Install Protoc
260255
run: |
@@ -860,12 +855,7 @@ jobs:
860855
uses: ./.github/actions/setup-go
861856

862857
- name: Install go tools
863-
run: |
864-
go install google.golang.org/protobuf/cmd/[email protected]
865-
go install storj.io/drpc/cmd/[email protected]
866-
go install golang.org/x/tools/cmd/[email protected]
867-
go install github.com/mikefarah/yq/[email protected]
868-
go install go.uber.org/mock/[email protected]
858+
uses: ./.github/actions/setup-go-tools
869859

870860
- name: Setup sqlc
871861
uses: ./.github/actions/setup-sqlc

.github/workflows/release.yaml

+52
Original file line numberDiff line numberDiff line change
@@ -924,3 +924,55 @@ jobs:
924924
continue-on-error: true
925925
run: |
926926
make sqlc-push
927+
928+
update-calendar:
929+
name: "Update release calendar in docs"
930+
runs-on: "ubuntu-latest"
931+
needs: [release, publish-homebrew, publish-winget, publish-sqlc]
932+
if: ${{ !inputs.dry_run }}
933+
permissions:
934+
contents: write
935+
pull-requests: write
936+
steps:
937+
- name: Harden Runner
938+
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
939+
with:
940+
egress-policy: audit
941+
942+
- name: Checkout repository
943+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
944+
with:
945+
fetch-depth: 0 # Needed to get all tags for version calculation
946+
947+
- name: Set up Git
948+
run: |
949+
git config user.name "Coder CI"
950+
git config user.email "[email protected]"
951+
952+
- name: Run update script
953+
run: |
954+
./scripts/update-release-calendar.sh
955+
make fmt/markdown
956+
957+
- name: Check for changes
958+
id: check_changes
959+
run: |
960+
if git diff --quiet docs/install/releases/index.md; then
961+
echo "No changes detected in release calendar."
962+
echo "changes=false" >> $GITHUB_OUTPUT
963+
else
964+
echo "Changes detected in release calendar."
965+
echo "changes=true" >> $GITHUB_OUTPUT
966+
fi
967+
968+
- name: Create Pull Request
969+
if: steps.check_changes.outputs.changes == 'true'
970+
uses: peter-evans/create-pull-request@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0
971+
with:
972+
commit-message: "docs: update release calendar"
973+
title: "docs: update release calendar"
974+
body: |
975+
This PR automatically updates the release calendar in the docs.
976+
branch: bot/update-release-calendar
977+
delete-branch: true
978+
labels: docs

Makefile

+11-11
Original file line numberDiff line numberDiff line change
@@ -813,8 +813,8 @@ coderd/apidoc/swagger.json: site/node_modules/.installed coderd/apidoc/.gen
813813
touch "$@"
814814

815815
update-golden-files:
816-
echo 'WARNING: This target is deprecated. Use "make gen/golden-files" instead.' 2>&1
817-
echo 'Running "make gen/golden-files"' 2>&1
816+
echo 'WARNING: This target is deprecated. Use "make gen/golden-files" instead.' >&2
817+
echo 'Running "make gen/golden-files"' >&2
818818
make gen/golden-files
819819
.PHONY: update-golden-files
820820

@@ -834,39 +834,39 @@ clean/golden-files:
834834
.PHONY: clean/golden-files
835835

836836
cli/testdata/.gen-golden: $(wildcard cli/testdata/*.golden) $(wildcard cli/*.tpl) $(GO_SRC_FILES) $(wildcard cli/*_test.go)
837-
go test ./cli -run="Test(CommandHelp|ServerYAML|ErrorExamples|.*Golden)" -update
837+
TZ=UTC go test ./cli -run="Test(CommandHelp|ServerYAML|ErrorExamples|.*Golden)" -update
838838
touch "$@"
839839

840840
enterprise/cli/testdata/.gen-golden: $(wildcard enterprise/cli/testdata/*.golden) $(wildcard cli/*.tpl) $(GO_SRC_FILES) $(wildcard enterprise/cli/*_test.go)
841-
go test ./enterprise/cli -run="TestEnterpriseCommandHelp" -update
841+
TZ=UTC go test ./enterprise/cli -run="TestEnterpriseCommandHelp" -update
842842
touch "$@"
843843

844844
tailnet/testdata/.gen-golden: $(wildcard tailnet/testdata/*.golden.html) $(GO_SRC_FILES) $(wildcard tailnet/*_test.go)
845-
go test ./tailnet -run="TestDebugTemplate" -update
845+
TZ=UTC go test ./tailnet -run="TestDebugTemplate" -update
846846
touch "$@"
847847

848848
enterprise/tailnet/testdata/.gen-golden: $(wildcard enterprise/tailnet/testdata/*.golden.html) $(GO_SRC_FILES) $(wildcard enterprise/tailnet/*_test.go)
849-
go test ./enterprise/tailnet -run="TestDebugTemplate" -update
849+
TZ=UTC go test ./enterprise/tailnet -run="TestDebugTemplate" -update
850850
touch "$@"
851851

852852
helm/coder/tests/testdata/.gen-golden: $(wildcard helm/coder/tests/testdata/*.yaml) $(wildcard helm/coder/tests/testdata/*.golden) $(GO_SRC_FILES) $(wildcard helm/coder/tests/*_test.go)
853-
go test ./helm/coder/tests -run=TestUpdateGoldenFiles -update
853+
TZ=UTC go test ./helm/coder/tests -run=TestUpdateGoldenFiles -update
854854
touch "$@"
855855

856856
helm/provisioner/tests/testdata/.gen-golden: $(wildcard helm/provisioner/tests/testdata/*.yaml) $(wildcard helm/provisioner/tests/testdata/*.golden) $(GO_SRC_FILES) $(wildcard helm/provisioner/tests/*_test.go)
857-
go test ./helm/provisioner/tests -run=TestUpdateGoldenFiles -update
857+
TZ=UTC go test ./helm/provisioner/tests -run=TestUpdateGoldenFiles -update
858858
touch "$@"
859859

860860
coderd/.gen-golden: $(wildcard coderd/testdata/*/*.golden) $(GO_SRC_FILES) $(wildcard coderd/*_test.go)
861-
go test ./coderd -run="Test.*Golden$$" -update
861+
TZ=UTC go test ./coderd -run="Test.*Golden$$" -update
862862
touch "$@"
863863

864864
coderd/notifications/.gen-golden: $(wildcard coderd/notifications/testdata/*/*.golden) $(GO_SRC_FILES) $(wildcard coderd/notifications/*_test.go)
865-
go test ./coderd/notifications -run="Test.*Golden$$" -update
865+
TZ=UTC go test ./coderd/notifications -run="Test.*Golden$$" -update
866866
touch "$@"
867867

868868
provisioner/terraform/testdata/.gen-golden: $(wildcard provisioner/terraform/testdata/*/*.golden) $(GO_SRC_FILES) $(wildcard provisioner/terraform/*_test.go)
869-
go test ./provisioner/terraform -run="Test.*Golden$$" -update
869+
TZ=UTC go test ./provisioner/terraform -run="Test.*Golden$$" -update
870870
touch "$@"
871871

872872
provisioner/terraform/testdata/version:

agent/ls.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,14 @@ func listFiles(query LSRequest) (LSResponse, error) {
125125
}
126126

127127
func listDrives() (LSResponse, error) {
128+
// disk.Partitions() will return partitions even if there was a failure to
129+
// get one. Any errored partitions will not be returned.
128130
partitionStats, err := disk.Partitions(true)
129-
if err != nil {
131+
if err != nil && len(partitionStats) == 0 {
132+
// Only return the error if there were no partitions returned.
130133
return LSResponse{}, xerrors.Errorf("failed to get partitions: %w", err)
131134
}
135+
132136
contents := make([]LSFile, 0, len(partitionStats))
133137
for _, a := range partitionStats {
134138
// Drive letters on Windows have a trailing separator as part of their name.

cli/cliui/prompt.go

+65-8
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
package cliui
22

33
import (
4+
"bufio"
45
"bytes"
56
"encoding/json"
67
"fmt"
78
"io"
89
"os"
910
"os/signal"
1011
"strings"
12+
"unicode"
1113

12-
"github.com/bgentry/speakeasy"
1314
"github.com/mattn/go-isatty"
1415
"golang.org/x/xerrors"
1516

17+
"github.com/coder/coder/v2/pty"
1618
"github.com/coder/pretty"
1719
"github.com/coder/serpent"
1820
)
1921

2022
// PromptOptions supply a set of options to the prompt.
2123
type PromptOptions struct {
22-
Text string
23-
Default string
24+
Text string
25+
Default string
26+
// When true, the input will be masked with asterisks.
2427
Secret bool
2528
IsConfirm bool
2629
Validate func(string) error
@@ -88,14 +91,13 @@ func Prompt(inv *serpent.Invocation, opts PromptOptions) (string, error) {
8891
var line string
8992
var err error
9093

94+
signal.Notify(interrupt, os.Interrupt)
95+
defer signal.Stop(interrupt)
96+
9197
inFile, isInputFile := inv.Stdin.(*os.File)
9298
if opts.Secret && isInputFile && isatty.IsTerminal(inFile.Fd()) {
93-
// we don't install a signal handler here because speakeasy has its own
94-
line, err = speakeasy.Ask("")
99+
line, err = readSecretInput(inFile, inv.Stdout)
95100
} else {
96-
signal.Notify(interrupt, os.Interrupt)
97-
defer signal.Stop(interrupt)
98-
99101
line, err = readUntil(inv.Stdin, '\n')
100102

101103
// Check if the first line beings with JSON object or array chars.
@@ -204,3 +206,58 @@ func readUntil(r io.Reader, delim byte) (string, error) {
204206
}
205207
}
206208
}
209+
210+
// readSecretInput reads secret input from the terminal rune-by-rune,
211+
// masking each character with an asterisk.
212+
func readSecretInput(f *os.File, w io.Writer) (string, error) {
213+
// Put terminal into raw mode (no echo, no line buffering).
214+
oldState, err := pty.MakeInputRaw(f.Fd())
215+
if err != nil {
216+
return "", err
217+
}
218+
defer func() {
219+
_ = pty.RestoreTerminal(f.Fd(), oldState)
220+
}()
221+
222+
reader := bufio.NewReader(f)
223+
var runes []rune
224+
225+
for {
226+
r, _, err := reader.ReadRune()
227+
if err != nil {
228+
return "", err
229+
}
230+
231+
switch {
232+
case r == '\r' || r == '\n':
233+
// Finish on Enter
234+
if _, err := fmt.Fprint(w, "\r\n"); err != nil {
235+
return "", err
236+
}
237+
return string(runes), nil
238+
239+
case r == 3:
240+
// Ctrl+C
241+
return "", ErrCanceled
242+
243+
case r == 127 || r == '\b':
244+
// Backspace/Delete: remove last rune
245+
if len(runes) > 0 {
246+
// Erase the last '*' on the screen
247+
if _, err := fmt.Fprint(w, "\b \b"); err != nil {
248+
return "", err
249+
}
250+
runes = runes[:len(runes)-1]
251+
}
252+
253+
default:
254+
// Only mask printable, non-control runes
255+
if !unicode.IsControl(r) {
256+
runes = append(runes, r)
257+
if _, err := fmt.Fprint(w, "*"); err != nil {
258+
return "", err
259+
}
260+
}
261+
}
262+
}
263+
}

cli/cliui/prompt_test.go

+51-15
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import (
66
"io"
77
"os"
88
"os/exec"
9+
"runtime"
910
"testing"
1011

1112
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
1314
"golang.org/x/xerrors"
1415

1516
"github.com/coder/coder/v2/cli/cliui"
16-
"github.com/coder/coder/v2/pty"
1717
"github.com/coder/coder/v2/pty/ptytest"
1818
"github.com/coder/coder/v2/testutil"
1919
"github.com/coder/serpent"
@@ -181,6 +181,48 @@ func TestPrompt(t *testing.T) {
181181
resp := testutil.TryReceive(ctx, t, doneChan)
182182
require.Equal(t, "valid", resp)
183183
})
184+
185+
t.Run("MaskedSecret", func(t *testing.T) {
186+
t.Parallel()
187+
ctx := testutil.Context(t, testutil.WaitShort)
188+
ptty := ptytest.New(t)
189+
doneChan := make(chan string)
190+
go func() {
191+
resp, err := newPrompt(ctx, ptty, cliui.PromptOptions{
192+
Text: "Password:",
193+
Secret: true,
194+
}, nil)
195+
assert.NoError(t, err)
196+
doneChan <- resp
197+
}()
198+
ptty.ExpectMatch("Password: ")
199+
200+
ptty.WriteLine("test")
201+
202+
resp := testutil.TryReceive(ctx, t, doneChan)
203+
require.Equal(t, "test", resp)
204+
})
205+
206+
t.Run("UTF8Password", func(t *testing.T) {
207+
t.Parallel()
208+
ctx := testutil.Context(t, testutil.WaitShort)
209+
ptty := ptytest.New(t)
210+
doneChan := make(chan string)
211+
go func() {
212+
resp, err := newPrompt(ctx, ptty, cliui.PromptOptions{
213+
Text: "Password:",
214+
Secret: true,
215+
}, nil)
216+
assert.NoError(t, err)
217+
doneChan <- resp
218+
}()
219+
ptty.ExpectMatch("Password: ")
220+
221+
ptty.WriteLine("和製漢字")
222+
223+
resp := testutil.TryReceive(ctx, t, doneChan)
224+
require.Equal(t, "和製漢字", resp)
225+
})
184226
}
185227

186228
func newPrompt(ctx context.Context, ptty *ptytest.PTY, opts cliui.PromptOptions, invOpt func(inv *serpent.Invocation)) (string, error) {
@@ -209,13 +251,12 @@ func TestPasswordTerminalState(t *testing.T) {
209251
passwordHelper()
210252
return
211253
}
254+
if runtime.GOOS == "windows" {
255+
t.Skip("Skipping on windows. PTY doesn't read ptty.Write correctly.")
256+
}
212257
t.Parallel()
213258

214259
ptty := ptytest.New(t)
215-
ptyWithFlags, ok := ptty.PTY.(pty.WithFlags)
216-
if !ok {
217-
t.Skip("unable to check PTY local echo on this platform")
218-
}
219260

220261
cmd := exec.Command(os.Args[0], "-test.run=TestPasswordTerminalState") //nolint:gosec
221262
cmd.Env = append(os.Environ(), "TEST_SUBPROCESS=1")
@@ -229,21 +270,16 @@ func TestPasswordTerminalState(t *testing.T) {
229270
defer process.Kill()
230271

231272
ptty.ExpectMatch("Password: ")
232-
233-
require.Eventually(t, func() bool {
234-
echo, err := ptyWithFlags.EchoEnabled()
235-
return err == nil && !echo
236-
}, testutil.WaitShort, testutil.IntervalMedium, "echo is on while reading password")
273+
ptty.Write('t')
274+
ptty.Write('e')
275+
ptty.Write('s')
276+
ptty.Write('t')
277+
ptty.ExpectMatch("****")
237278

238279
err = process.Signal(os.Interrupt)
239280
require.NoError(t, err)
240281
_, err = process.Wait()
241282
require.NoError(t, err)
242-
243-
require.Eventually(t, func() bool {
244-
echo, err := ptyWithFlags.EchoEnabled()
245-
return err == nil && echo
246-
}, testutil.WaitShort, testutil.IntervalMedium, "echo is off after reading password")
247283
}
248284

249285
// nolint:unused

0 commit comments

Comments
 (0)