Skip to content

Commit 0808361

Browse files
committed
Merge branch 'main' into lilac/storybook-9
# Conflicts: # site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx
2 parents bba8889 + 71738f6 commit 0808361

File tree

76 files changed

+1701
-453
lines changed

Some content is hidden

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

76 files changed

+1701
-453
lines changed

.github/workflows/ci.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,27 @@ jobs:
10601060
- name: Setup Go
10611061
uses: ./.github/actions/setup-go
10621062

1063+
- name: Install rcodesign
1064+
run: |
1065+
set -euo pipefail
1066+
wget -O /tmp/rcodesign.tar.gz https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-x86_64-unknown-linux-musl.tar.gz
1067+
sudo tar -xzf /tmp/rcodesign.tar.gz \
1068+
-C /usr/bin \
1069+
--strip-components=1 \
1070+
apple-codesign-0.22.0-x86_64-unknown-linux-musl/rcodesign
1071+
rm /tmp/rcodesign.tar.gz
1072+
1073+
- name: Setup Apple Developer certificate
1074+
run: |
1075+
set -euo pipefail
1076+
touch /tmp/{apple_cert.p12,apple_cert_password.txt}
1077+
chmod 600 /tmp/{apple_cert.p12,apple_cert_password.txt}
1078+
echo "$AC_CERTIFICATE_P12_BASE64" | base64 -d > /tmp/apple_cert.p12
1079+
echo "$AC_CERTIFICATE_PASSWORD" > /tmp/apple_cert_password.txt
1080+
env:
1081+
AC_CERTIFICATE_P12_BASE64: ${{ secrets.AC_CERTIFICATE_P12_BASE64 }}
1082+
AC_CERTIFICATE_PASSWORD: ${{ secrets.AC_CERTIFICATE_PASSWORD }}
1083+
10631084
# Necessary for signing Windows binaries.
10641085
- name: Setup Java
10651086
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
@@ -1138,6 +1159,9 @@ jobs:
11381159
CODER_WINDOWS_RESOURCES: "1"
11391160
CODER_SIGN_GPG: "1"
11401161
CODER_GPG_RELEASE_KEY_BASE64: ${{ secrets.GPG_RELEASE_KEY_BASE64 }}
1162+
CODER_SIGN_DARWIN: "1"
1163+
AC_CERTIFICATE_FILE: /tmp/apple_cert.p12
1164+
AC_CERTIFICATE_PASSWORD_FILE: /tmp/apple_cert_password.txt
11411165
EV_KEY: ${{ secrets.EV_KEY }}
11421166
EV_KEYSTORE: ${{ secrets.EV_KEYSTORE }}
11431167
EV_TSA_URL: ${{ secrets.EV_TSA_URL }}

agent/agentcontainers/watcher/watcher_test.go

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"os"
66
"path/filepath"
7+
"runtime"
78
"testing"
89

910
"github.com/fsnotify/fsnotify"
@@ -88,24 +89,34 @@ func TestFSNotifyWatcher(t *testing.T) {
8889
break
8990
}
9091

91-
err = os.WriteFile(testFile+".atomic", []byte(`{"test": "atomic"}`), 0o600)
92-
require.NoError(t, err, "write new atomic test file failed")
93-
94-
err = os.Rename(testFile+".atomic", testFile)
95-
require.NoError(t, err, "rename atomic test file failed")
96-
97-
// Verify that we receive the event we want.
98-
for {
99-
event, err := wut.Next(ctx)
100-
require.NoError(t, err, "next event failed")
101-
require.NotNil(t, event, "want non-nil event")
102-
if !event.Has(fsnotify.Create) {
103-
t.Logf("Ignoring event: %s", event)
104-
continue
92+
// TODO(DanielleMaywood):
93+
// Unfortunately it appears this atomic-rename phase of the test is flakey on macOS.
94+
//
95+
// This test flake could be indicative of an issue that may present itself
96+
// in a running environment. Fortunately, we only use this (as of 2025-07-29)
97+
// for our dev container integration. We do not expect the host workspace
98+
// (where this is used), to ever be run on macOS, as containers are a linux
99+
// paradigm.
100+
if runtime.GOOS != "darwin" {
101+
err = os.WriteFile(testFile+".atomic", []byte(`{"test": "atomic"}`), 0o600)
102+
require.NoError(t, err, "write new atomic test file failed")
103+
104+
err = os.Rename(testFile+".atomic", testFile)
105+
require.NoError(t, err, "rename atomic test file failed")
106+
107+
// Verify that we receive the event we want.
108+
for {
109+
event, err := wut.Next(ctx)
110+
require.NoError(t, err, "next event failed")
111+
require.NotNil(t, event, "want non-nil event")
112+
if !event.Has(fsnotify.Create) {
113+
t.Logf("Ignoring event: %s", event)
114+
continue
115+
}
116+
require.Truef(t, event.Has(fsnotify.Create), "want create event: %s", event.String())
117+
require.Equal(t, event.Name, testFile, "want event for test file")
118+
break
105119
}
106-
require.Truef(t, event.Has(fsnotify.Create), "want create event: %s", event.String())
107-
require.Equal(t, event.Name, testFile, "want event for test file")
108-
break
109120
}
110121

111122
// Test removing the file from the watcher.

cli/create.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,12 @@ func promptPresetSelection(inv *serpent.Invocation, presets []codersdk.Preset) (
472472
var presetOptions []string
473473

474474
for _, preset := range presets {
475-
option := preset.Name
475+
var option string
476+
if preset.Description == "" {
477+
option = preset.Name
478+
} else {
479+
option = fmt.Sprintf("%s: %s", preset.Name, preset.Description)
480+
}
476481
presetOptions = append(presetOptions, option)
477482
presetMap[option] = &preset
478483
}

cli/create_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,8 @@ func TestCreateWithPreset(t *testing.T) {
882882

883883
// Given: a template and a template version with two presets
884884
preset := proto.Preset{
885-
Name: "preset-test",
885+
Name: "preset-test",
886+
Description: "Preset Test.",
886887
Parameters: []*proto.PresetParameter{
887888
{Name: firstParameterName, Value: secondOptionalParameterValue},
888889
{Name: thirdParameterName, Value: thirdParameterValue},

cli/restart.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,17 @@ func (r *RootCmd) restart() *serpent.Command {
5151
return err
5252
}
5353

54+
stopParamValues, err := asWorkspaceBuildParameters(parameterFlags.ephemeralParameters)
55+
if err != nil {
56+
return xerrors.Errorf("parse ephemeral parameters: %w", err)
57+
}
5458
wbr := codersdk.CreateWorkspaceBuildRequest{
5559
Transition: codersdk.WorkspaceTransitionStop,
60+
// Ephemeral parameters should be passed to both stop and start builds.
61+
// TODO: maybe these values should be sourced from the previous build?
62+
// It has to be manually sourced, as ephemeral parameters do not carry across
63+
// builds.
64+
RichParameterValues: stopParamValues,
5665
}
5766
if bflags.provisionerLogDebug {
5867
wbr.LogLevel = codersdk.ProvisionerLogLevelDebug

cli/restart_test.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/coder/coder/v2/cli/clitest"
1212
"github.com/coder/coder/v2/coderd/coderdtest"
13+
"github.com/coder/coder/v2/coderd/util/ptr"
1314
"github.com/coder/coder/v2/codersdk"
1415
"github.com/coder/coder/v2/provisioner/echo"
1516
"github.com/coder/coder/v2/provisionersdk/proto"
@@ -70,8 +71,14 @@ func TestRestart(t *testing.T) {
7071
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
7172
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses())
7273
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
73-
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
74-
workspace := coderdtest.CreateWorkspace(t, member, template.ID)
74+
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
75+
request.UseClassicParameterFlow = ptr.Ref(true) // TODO: Remove when dynamic parameters prompt missing ephemeral parameters.
76+
})
77+
workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
78+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
79+
{Name: ephemeralParameterName, Value: "placeholder"},
80+
}
81+
})
7582
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
7683

7784
inv, root := clitest.New(t, "restart", workspace.Name, "--prompt-ephemeral-parameters")
@@ -125,7 +132,11 @@ func TestRestart(t *testing.T) {
125132
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses())
126133
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
127134
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
128-
workspace := coderdtest.CreateWorkspace(t, member, template.ID)
135+
workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
136+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
137+
{Name: ephemeralParameterName, Value: "placeholder"},
138+
}
139+
})
129140
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
130141

131142
inv, root := clitest.New(t, "restart", workspace.Name,
@@ -178,8 +189,14 @@ func TestRestart(t *testing.T) {
178189
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
179190
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses())
180191
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
181-
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
182-
workspace := coderdtest.CreateWorkspace(t, member, template.ID)
192+
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) {
193+
request.UseClassicParameterFlow = ptr.Ref(true) // TODO: Remove when dynamic parameters prompts missing ephemeral parameters
194+
})
195+
workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
196+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
197+
{Name: ephemeralParameterName, Value: "placeholder"},
198+
}
199+
})
183200
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
184201

185202
inv, root := clitest.New(t, "restart", workspace.Name, "--build-options")
@@ -233,7 +250,11 @@ func TestRestart(t *testing.T) {
233250
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses())
234251
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
235252
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
236-
workspace := coderdtest.CreateWorkspace(t, member, template.ID)
253+
workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
254+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
255+
{Name: ephemeralParameterName, Value: "placeholder"},
256+
}
257+
})
237258
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
238259

239260
inv, root := clitest.New(t, "restart", workspace.Name,

cli/start_test.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,18 @@ func TestStart(t *testing.T) {
113113
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses())
114114
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
115115
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
116-
workspace := coderdtest.CreateWorkspace(t, member, template.ID)
116+
workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
117+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
118+
{Name: ephemeralParameterName, Value: "foo"}, // Value is required, set it to something
119+
}
120+
})
117121
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
118122
// Stop the workspace
119-
workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop)
123+
workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop, func(request *codersdk.CreateWorkspaceBuildRequest) {
124+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
125+
{Name: ephemeralParameterName, Value: "foo"}, // Value is required, set it to something
126+
}
127+
})
120128
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspaceBuild.ID)
121129

122130
inv, root := clitest.New(t, "start", workspace.Name, "--prompt-ephemeral-parameters")
@@ -167,10 +175,18 @@ func TestStart(t *testing.T) {
167175
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses())
168176
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
169177
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
170-
workspace := coderdtest.CreateWorkspace(t, member, template.ID)
178+
workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
179+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
180+
{Name: ephemeralParameterName, Value: "foo"}, // Value is required, set it to something
181+
}
182+
})
171183
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
172184
// Stop the workspace
173-
workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop)
185+
workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop, func(request *codersdk.CreateWorkspaceBuildRequest) {
186+
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
187+
{Name: ephemeralParameterName, Value: "foo"}, // Value is required, set it to something
188+
}
189+
})
174190
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspaceBuild.ID)
175191

176192
inv, root := clitest.New(t, "start", workspace.Name,

cli/templatepresets.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,13 @@ func (r *RootCmd) templatePresets() *serpent.Command {
4141
func (r *RootCmd) templatePresetsList() *serpent.Command {
4242
defaultColumns := []string{
4343
"name",
44+
"description",
4445
"parameters",
4546
"default",
4647
"desired prebuild instances",
4748
}
4849
formatter := cliui.NewOutputFormatter(
49-
cliui.TableFormat([]templatePresetRow{}, defaultColumns),
50+
cliui.TableFormat([]TemplatePresetRow{}, defaultColumns),
5051
cliui.JSONFormat(),
5152
)
5253
client := new(codersdk.Client)
@@ -108,10 +109,13 @@ func (r *RootCmd) templatePresetsList() *serpent.Command {
108109
return nil
109110
}
110111

111-
cliui.Infof(
112-
inv.Stdout,
113-
"Showing presets for template %q and template version %q.\n", template.Name, version.Name,
114-
)
112+
// Only display info message for table output
113+
if formatter.FormatID() == "table" {
114+
cliui.Infof(
115+
inv.Stdout,
116+
"Showing presets for template %q and template version %q.\n", template.Name, version.Name,
117+
)
118+
}
115119
rows := templatePresetsToRows(presets...)
116120
out, err := formatter.Format(inv.Context(), rows)
117121
if err != nil {
@@ -128,12 +132,13 @@ func (r *RootCmd) templatePresetsList() *serpent.Command {
128132
return cmd
129133
}
130134

131-
type templatePresetRow struct {
132-
// For json format:
135+
type TemplatePresetRow struct {
136+
// For json format
133137
TemplatePreset codersdk.Preset `table:"-"`
134138

135139
// For table format:
136140
Name string `json:"-" table:"name,default_sort"`
141+
Description string `json:"-" table:"description"`
137142
Parameters string `json:"-" table:"parameters"`
138143
Default bool `json:"-" table:"default"`
139144
DesiredPrebuildInstances string `json:"-" table:"desired prebuild instances"`
@@ -149,15 +154,19 @@ func formatPresetParameters(params []codersdk.PresetParameter) string {
149154

150155
// templatePresetsToRows converts a list of presets to a list of rows
151156
// for outputting.
152-
func templatePresetsToRows(presets ...codersdk.Preset) []templatePresetRow {
153-
rows := make([]templatePresetRow, len(presets))
157+
func templatePresetsToRows(presets ...codersdk.Preset) []TemplatePresetRow {
158+
rows := make([]TemplatePresetRow, len(presets))
154159
for i, preset := range presets {
155160
prebuildInstances := "-"
156161
if preset.DesiredPrebuildInstances != nil {
157162
prebuildInstances = strconv.Itoa(*preset.DesiredPrebuildInstances)
158163
}
159-
rows[i] = templatePresetRow{
164+
rows[i] = TemplatePresetRow{
165+
// For json format
166+
TemplatePreset: preset,
167+
// For table format
160168
Name: preset.Name,
169+
Description: preset.Description,
161170
Parameters: formatPresetParameters(preset.Parameters),
162171
Default: preset.Default,
163172
DesiredPrebuildInstances: prebuildInstances,

0 commit comments

Comments
 (0)