Skip to content

Commit 5058869

Browse files
committed
Merge branch 'yevhenii/512-claim-prebuild' of github.com:/coder/coder into dk/enable-prebuilds
2 parents cf03e58 + fa65564 commit 5058869

File tree

16 files changed

+473
-59
lines changed

16 files changed

+473
-59
lines changed
Lines changed: 14 additions & 0 deletions
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/protoc-gen-go@v1.30
11+
go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.34
12+
go install golang.org/x/tools/cmd/goimports@v0.31.0
13+
go install github.com/mikefarah/yq/v4@v4.44.3
14+
go install go.uber.org/mock/mockgen@v0.5.0

.github/workflows/ci.yaml

Lines changed: 2 additions & 12 deletions
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/protoc-gen-go@v1.30
254-
go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.34
255-
go install golang.org/x/tools/cmd/goimports@v0.31.0
256-
go install github.com/mikefarah/yq/v4@v4.44.3
257-
go install go.uber.org/mock/mockgen@v0.5.0
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/protoc-gen-go@v1.30
865-
go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.34
866-
go install golang.org/x/tools/cmd/goimports@v0.31.0
867-
go install github.com/mikefarah/yq/v4@v4.44.3
868-
go install go.uber.org/mock/mockgen@v0.5.0
858+
uses: ./.github/actions/setup-go-tools
869859

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

.github/workflows/release.yaml

Lines changed: 52 additions & 0 deletions
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 "cdrci@coder.com"
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

cli/cliui/prompt.go

Lines changed: 65 additions & 8 deletions
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

Lines changed: 51 additions & 15 deletions
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

docs/install/releases/index.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,18 @@ Best practices for installing Coder can be found on our [install](../index.md)
5353
pages.
5454

5555
## Release schedule
56-
57-
| Release name | Release Date | Status |
58-
|--------------|--------------------|------------------|
59-
| 2.12.x | June 04, 2024 | Not Supported |
60-
| 2.13.x | July 02, 2024 | Not Supported |
61-
| 2.14.x | August 06, 2024 | Not Supported |
62-
| 2.15.x | September 03, 2024 | Not Supported |
63-
| 2.16.x | October 01, 2024 | Not Supported |
64-
| 2.17.x | November 05, 2024 | Not Supported |
65-
| 2.18.x | December 03, 2024 | Security Support |
66-
| 2.19.x | February 04, 2024 | Stable |
67-
| 2.20.x | March 05, 2024 | Mainline |
56+
<!-- Autogenerated release calendar from scripts/update-release-calendar.sh -->
57+
<!-- RELEASE_CALENDAR_START -->
58+
| Release name | Release Date | Status | Latest Release |
59+
|------------------------------------------------|-------------------|------------------|----------------------------------------------------------------|
60+
| [2.16](https://coder.com/changelog/coder-2-16) | November 05, 2024 | Not Supported | [v2.16.1](https://github.com/coder/coder/releases/tag/v2.16.1) |
61+
| [2.17](https://coder.com/changelog/coder-2-17) | December 03, 2024 | Not Supported | [v2.17.3](https://github.com/coder/coder/releases/tag/v2.17.3) |
62+
| [2.18](https://coder.com/changelog/coder-2-18) | February 04, 2025 | Not Supported | [v2.18.5](https://github.com/coder/coder/releases/tag/v2.18.5) |
63+
| [2.19](https://coder.com/changelog/coder-2-19) | February 04, 2025 | Security Support | [v2.19.1](https://github.com/coder/coder/releases/tag/v2.19.1) |
64+
| [2.20](https://coder.com/changelog/coder-2-20) | March 04, 2025 | Stable | [v2.20.2](https://github.com/coder/coder/releases/tag/v2.20.2) |
65+
| [2.21](https://coder.com/changelog/coder-2-21) | April 01, 2025 | Mainline | [v2.21.1](https://github.com/coder/coder/releases/tag/v2.21.1) |
66+
| 2.22 | May 07, 2024 | Not Released | N/A |
67+
<!-- RELEASE_CALENDAR_END -->
6868

6969
> [!TIP]
7070
> We publish a

docs/tutorials/testing-templates.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ jobs:
105105
coder create -t $TEMPLATE_NAME --template-version ${{ steps.name.outputs.version_name }} test-${{ steps.name.outputs.version_name }} --yes
106106
coder config-ssh --yes
107107
# run some example commands
108-
coder ssh test-${{ steps.name.outputs.version_name }} -- make build
108+
ssh coder.test-${{ steps.name.outputs.version_name }} -- make build
109109
110110
- name: Delete the test workspace
111111
if: always()

dogfood/coder/main.tf

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ terraform {
22
required_providers {
33
coder = {
44
source = "coder/coder"
5-
version = "2.3.0"
5+
version = "~> 2.0"
66
}
77
docker = {
88
source = "kreuzwerker/docker"
9-
version = "~> 3.0.0"
9+
version = "~> 3.0"
1010
}
1111
}
1212
}
@@ -225,6 +225,14 @@ module "cursor" {
225225
folder = local.repo_dir
226226
}
227227

228+
module "windsurf" {
229+
count = data.coder_workspace.me.start_count
230+
source = "registry.coder.com/modules/windsurf/coder"
231+
version = ">= 1.0.0"
232+
agent_id = coder_agent.dev.id
233+
folder = local.repo_dir
234+
}
235+
228236
module "zed" {
229237
count = data.coder_workspace.me.start_count
230238
source = "./zed"

0 commit comments

Comments
 (0)