Skip to content

Commit 92a125e

Browse files
committed
Merge branch 'main' into dean/output-formats
2 parents 3eb6813 + 5655ec6 commit 92a125e

Some content is hidden

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

57 files changed

+922
-189
lines changed

.github/workflows/release.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ jobs:
6363
6464
- name: Create release notes
6565
env:
66+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6667
# We always have to set this since there might be commits on
6768
# main that didn't have a PR.
6869
CODER_IGNORE_MISSING_COMMIT_METADATA: "1"
@@ -288,6 +289,7 @@ jobs:
288289
retention-days: 7
289290

290291
- name: Start Packer builds
292+
if: ${{ !inputs.dry_run }}
291293
uses: peter-evans/repository-dispatch@v2
292294
with:
293295
token: ${{ secrets.CDRCI_GITHUB_TOKEN }}

.github/workflows/security.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ jobs:
9292
restore-keys: |
9393
js-${{ runner.os }}-
9494
95+
- name: Install yq
96+
run: go run github.com/mikefarah/yq/v4@v4.30.6
97+
9598
- name: Build Coder linux amd64 Docker image
9699
id: build
97100
run: |
@@ -124,6 +127,7 @@ jobs:
124127
uses: github/codeql-action/upload-sarif@v2
125128
with:
126129
sarif_file: trivy-results.sarif
130+
category: "Trivy"
127131

128132
- name: Upload Trivy scan results as an artifact
129133
uses: actions/upload-artifact@v2

agent/agent.go

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ type Client interface {
7575
ReportStats(ctx context.Context, log slog.Logger, stats func() *agentsdk.Stats) (io.Closer, error)
7676
PostLifecycle(ctx context.Context, state agentsdk.PostLifecycleRequest) error
7777
PostAppHealth(ctx context.Context, req agentsdk.PostAppHealthsRequest) error
78-
PostVersion(ctx context.Context, version string) error
78+
PostStartup(ctx context.Context, req agentsdk.PostStartupRequest) error
7979
}
8080

8181
func New(options Options) io.Closer {
@@ -236,16 +236,29 @@ func (a *agent) run(ctx context.Context) error {
236236
}
237237
a.sessionToken.Store(&sessionToken)
238238

239-
err = a.client.PostVersion(ctx, buildinfo.Version())
240-
if err != nil {
241-
return xerrors.Errorf("update workspace agent version: %w", err)
242-
}
243-
244239
metadata, err := a.client.Metadata(ctx)
245240
if err != nil {
246241
return xerrors.Errorf("fetch metadata: %w", err)
247242
}
248243
a.logger.Info(ctx, "fetched metadata")
244+
245+
// Expand the directory and send it back to coderd so external
246+
// applications that rely on the directory can use it.
247+
//
248+
// An example is VS Code Remote, which must know the directory
249+
// before initializing a connection.
250+
metadata.Directory, err = expandDirectory(metadata.Directory)
251+
if err != nil {
252+
return xerrors.Errorf("expand directory: %w", err)
253+
}
254+
err = a.client.PostStartup(ctx, agentsdk.PostStartupRequest{
255+
Version: buildinfo.Version(),
256+
ExpandedDirectory: metadata.Directory,
257+
})
258+
if err != nil {
259+
return xerrors.Errorf("update workspace agent version: %w", err)
260+
}
261+
249262
oldMetadata := a.metadata.Swap(metadata)
250263

251264
// The startup script should only execute on the first run!
@@ -803,7 +816,11 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
803816

804817
cmd := exec.CommandContext(ctx, shell, args...)
805818
cmd.Dir = metadata.Directory
806-
if cmd.Dir == "" {
819+
820+
// If the metadata directory doesn't exist, we run the command
821+
// in the users home directory.
822+
_, err = os.Stat(cmd.Dir)
823+
if cmd.Dir == "" || err != nil {
807824
// Default to user home if a directory is not set.
808825
homedir, err := userHomeDir()
809826
if err != nil {
@@ -1314,3 +1331,20 @@ func userHomeDir() (string, error) {
13141331
}
13151332
return u.HomeDir, nil
13161333
}
1334+
1335+
// expandDirectory converts a directory path to an absolute path.
1336+
// It primarily resolves the home directory and any environment
1337+
// variables that may be set
1338+
func expandDirectory(dir string) (string, error) {
1339+
if dir == "" {
1340+
return "", nil
1341+
}
1342+
if dir[0] == '~' {
1343+
home, err := userHomeDir()
1344+
if err != nil {
1345+
return "", err
1346+
}
1347+
dir = filepath.Join(home, dir[1:])
1348+
}
1349+
return os.ExpandEnv(dir), nil
1350+
}

agent/agent_test.go

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,56 @@ func TestAgent_Lifecycle(t *testing.T) {
787787
})
788788
}
789789

790+
func TestAgent_Startup(t *testing.T) {
791+
t.Parallel()
792+
793+
t.Run("EmptyDirectory", func(t *testing.T) {
794+
t.Parallel()
795+
796+
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
797+
StartupScript: "true",
798+
StartupScriptTimeout: 30 * time.Second,
799+
Directory: "",
800+
}, 0)
801+
assert.Eventually(t, func() bool {
802+
return client.getStartup().Version != ""
803+
}, testutil.WaitShort, testutil.IntervalFast)
804+
require.Equal(t, "", client.getStartup().ExpandedDirectory)
805+
})
806+
807+
t.Run("HomeDirectory", func(t *testing.T) {
808+
t.Parallel()
809+
810+
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
811+
StartupScript: "true",
812+
StartupScriptTimeout: 30 * time.Second,
813+
Directory: "~",
814+
}, 0)
815+
assert.Eventually(t, func() bool {
816+
return client.getStartup().Version != ""
817+
}, testutil.WaitShort, testutil.IntervalFast)
818+
homeDir, err := os.UserHomeDir()
819+
require.NoError(t, err)
820+
require.Equal(t, homeDir, client.getStartup().ExpandedDirectory)
821+
})
822+
823+
t.Run("HomeEnvironmentVariable", func(t *testing.T) {
824+
t.Parallel()
825+
826+
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
827+
StartupScript: "true",
828+
StartupScriptTimeout: 30 * time.Second,
829+
Directory: "$HOME",
830+
}, 0)
831+
assert.Eventually(t, func() bool {
832+
return client.getStartup().Version != ""
833+
}, testutil.WaitShort, testutil.IntervalFast)
834+
homeDir, err := os.UserHomeDir()
835+
require.NoError(t, err)
836+
require.Equal(t, homeDir, client.getStartup().ExpandedDirectory)
837+
})
838+
}
839+
790840
func TestAgent_ReconnectingPTY(t *testing.T) {
791841
t.Parallel()
792842
if runtime.GOOS == "windows" {
@@ -1178,6 +1228,7 @@ type client struct {
11781228

11791229
mu sync.Mutex // Protects following.
11801230
lifecycleStates []codersdk.WorkspaceAgentLifecycle
1231+
startup agentsdk.PostStartupRequest
11811232
}
11821233

11831234
func (c *client) Metadata(_ context.Context) (agentsdk.Metadata, error) {
@@ -1250,7 +1301,16 @@ func (*client) PostAppHealth(_ context.Context, _ agentsdk.PostAppHealthsRequest
12501301
return nil
12511302
}
12521303

1253-
func (*client) PostVersion(_ context.Context, _ string) error {
1304+
func (c *client) getStartup() agentsdk.PostStartupRequest {
1305+
c.mu.Lock()
1306+
defer c.mu.Unlock()
1307+
return c.startup
1308+
}
1309+
1310+
func (c *client) PostStartup(_ context.Context, startup agentsdk.PostStartupRequest) error {
1311+
c.mu.Lock()
1312+
defer c.mu.Unlock()
1313+
c.startup = startup
12541314
return nil
12551315
}
12561316

cli/cliui/parameter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ func ParameterSchema(cmd *cobra.Command, parameterSchema codersdk.ParameterSchem
6363

6464
func RichParameter(cmd *cobra.Command, templateVersionParameter codersdk.TemplateVersionParameter) (string, error) {
6565
_, _ = fmt.Fprintln(cmd.OutOrStdout(), Styles.Bold.Render(templateVersionParameter.Name))
66-
if templateVersionParameter.Description != "" {
67-
_, _ = fmt.Fprintln(cmd.OutOrStdout(), " "+strings.TrimSpace(strings.Join(strings.Split(templateVersionParameter.Description, "\n"), "\n "))+"\n")
66+
if templateVersionParameter.DescriptionPlaintext != "" {
67+
_, _ = fmt.Fprintln(cmd.OutOrStdout(), " "+strings.TrimSpace(strings.Join(strings.Split(templateVersionParameter.DescriptionPlaintext, "\n"), "\n "))+"\n")
6868
}
6969

7070
var err error

cli/server_createadminuser_test.go

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,17 @@ func TestServerCreateAdminUser(t *testing.T) {
8686
connectionURL, closeFunc, err := postgres.Open()
8787
require.NoError(t, err)
8888
defer closeFunc()
89-
ctx, cancelFunc := context.WithCancel(context.Background())
90-
defer cancelFunc()
9189

9290
sqlDB, err := sql.Open("postgres", connectionURL)
9391
require.NoError(t, err)
9492
defer sqlDB.Close()
9593
db := database.New(sqlDB)
9694

95+
// Sometimes generating SSH keys takes a really long time if there isn't
96+
// enough entropy. We don't want the tests to fail in these cases.
97+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitSuperLong)
98+
defer cancel()
99+
97100
pingCtx, pingCancel := context.WithTimeout(ctx, testutil.WaitShort)
98101
defer pingCancel()
99102
_, err = db.Ping(pingCtx)
@@ -135,14 +138,14 @@ func TestServerCreateAdminUser(t *testing.T) {
135138
errC <- err
136139
}()
137140

138-
pty.ExpectMatch("Creating user...")
139-
pty.ExpectMatch("Generating user SSH key...")
140-
pty.ExpectMatch(fmt.Sprintf("Adding user to organization %q (%s) as admin...", org1Name, org1ID.String()))
141-
pty.ExpectMatch(fmt.Sprintf("Adding user to organization %q (%s) as admin...", org2Name, org2ID.String()))
142-
pty.ExpectMatch("User created successfully.")
143-
pty.ExpectMatch(username)
144-
pty.ExpectMatch(email)
145-
pty.ExpectMatch("****")
141+
pty.ExpectMatchContext(ctx, "Creating user...")
142+
pty.ExpectMatchContext(ctx, "Generating user SSH key...")
143+
pty.ExpectMatchContext(ctx, fmt.Sprintf("Adding user to organization %q (%s) as admin...", org1Name, org1ID.String()))
144+
pty.ExpectMatchContext(ctx, fmt.Sprintf("Adding user to organization %q (%s) as admin...", org2Name, org2ID.String()))
145+
pty.ExpectMatchContext(ctx, "User created successfully.")
146+
pty.ExpectMatchContext(ctx, username)
147+
pty.ExpectMatchContext(ctx, email)
148+
pty.ExpectMatchContext(ctx, "****")
146149

147150
require.NoError(t, <-errC)
148151

@@ -158,11 +161,14 @@ func TestServerCreateAdminUser(t *testing.T) {
158161
connectionURL, closeFunc, err := postgres.Open()
159162
require.NoError(t, err)
160163
defer closeFunc()
161-
ctx, cancelFunc := context.WithCancel(context.Background())
162-
defer cancelFunc()
164+
165+
// Sometimes generating SSH keys takes a really long time if there isn't
166+
// enough entropy. We don't want the tests to fail in these cases.
167+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitSuperLong)
168+
defer cancel()
163169

164170
t.Setenv("CODER_POSTGRES_URL", connectionURL)
165-
t.Setenv("CODER_SSH_KEYGEN_ALGORITHM", "ecdsa")
171+
t.Setenv("CODER_SSH_KEYGEN_ALGORITHM", "ed25519")
166172
t.Setenv("CODER_USERNAME", username)
167173
t.Setenv("CODER_EMAIL", email)
168174
t.Setenv("CODER_PASSWORD", password)
@@ -178,10 +184,10 @@ func TestServerCreateAdminUser(t *testing.T) {
178184
errC <- err
179185
}()
180186

181-
pty.ExpectMatch("User created successfully.")
182-
pty.ExpectMatch(username)
183-
pty.ExpectMatch(email)
184-
pty.ExpectMatch("****")
187+
pty.ExpectMatchContext(ctx, "User created successfully.")
188+
pty.ExpectMatchContext(ctx, username)
189+
pty.ExpectMatchContext(ctx, email)
190+
pty.ExpectMatchContext(ctx, "****")
185191

186192
require.NoError(t, <-errC)
187193

@@ -198,13 +204,16 @@ func TestServerCreateAdminUser(t *testing.T) {
198204
connectionURL, closeFunc, err := postgres.Open()
199205
require.NoError(t, err)
200206
defer closeFunc()
201-
ctx, cancelFunc := context.WithCancel(context.Background())
202-
defer cancelFunc()
207+
208+
// Sometimes generating SSH keys takes a really long time if there isn't
209+
// enough entropy. We don't want the tests to fail in these cases.
210+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitSuperLong)
211+
defer cancel()
203212

204213
root, _ := clitest.New(t,
205214
"server", "create-admin-user",
206215
"--postgres-url", connectionURL,
207-
"--ssh-keygen-algorithm", "rsa4096",
216+
"--ssh-keygen-algorithm", "ed25519",
208217
)
209218
pty := ptytest.New(t)
210219
root.SetIn(pty.Input())
@@ -217,19 +226,19 @@ func TestServerCreateAdminUser(t *testing.T) {
217226
errC <- err
218227
}()
219228

220-
pty.ExpectMatch("> Username")
229+
pty.ExpectMatchContext(ctx, "> Username")
221230
pty.WriteLine(username)
222-
pty.ExpectMatch("> Email")
231+
pty.ExpectMatchContext(ctx, "> Email")
223232
pty.WriteLine(email)
224-
pty.ExpectMatch("> Password")
233+
pty.ExpectMatchContext(ctx, "> Password")
225234
pty.WriteLine(password)
226-
pty.ExpectMatch("> Confirm password")
235+
pty.ExpectMatchContext(ctx, "> Confirm password")
227236
pty.WriteLine(password)
228237

229-
pty.ExpectMatch("User created successfully.")
230-
pty.ExpectMatch(username)
231-
pty.ExpectMatch(email)
232-
pty.ExpectMatch("****")
238+
pty.ExpectMatchContext(ctx, "User created successfully.")
239+
pty.ExpectMatchContext(ctx, username)
240+
pty.ExpectMatchContext(ctx, email)
241+
pty.ExpectMatchContext(ctx, "****")
233242

234243
require.NoError(t, <-errC)
235244

coderd/apidoc/docs.go

Lines changed: 15 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)