Skip to content

Commit c8f38e0

Browse files
committed
Merge branch 'main' into mes/abbr-fix
2 parents 9a94037 + 2180d17 commit c8f38e0

File tree

41 files changed

+1325
-740
lines changed

Some content is hidden

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

41 files changed

+1325
-740
lines changed

.github/workflows/release.yaml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,36 @@ env:
3232
CODER_RELEASE_NOTES: ${{ inputs.release_notes }}
3333

3434
jobs:
35+
# Only allow maintainers/admins to release.
36+
check-perms:
37+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
38+
steps:
39+
- name: Allow only maintainers/admins
40+
uses: actions/github-script@v7.0.1
41+
with:
42+
github-token: ${{ secrets.GITHUB_TOKEN }}
43+
script: |
44+
const {data} = await github.rest.repos.getCollaboratorPermissionLevel({
45+
owner: context.repo.owner,
46+
repo: context.repo.repo,
47+
username: context.actor
48+
});
49+
const role = data.role_name || data.user?.role_name || data.permission;
50+
const perms = data.user?.permissions || {};
51+
core.info(`Actor ${context.actor} permission=${data.permission}, role_name=${role}`);
52+
53+
const allowed =
54+
role === 'admin' ||
55+
role === 'maintain' ||
56+
perms.admin === true ||
57+
perms.maintain === true;
58+
59+
if (!allowed) core.setFailed('Denied: requires maintain or admin');
60+
3561
# build-dylib is a separate job to build the dylib on macOS.
3662
build-dylib:
3763
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest' }}
64+
needs: check-perms
3865
steps:
3966
# Harden Runner doesn't work on macOS.
4067
- name: Checkout
@@ -114,7 +141,7 @@ jobs:
114141

115142
release:
116143
name: Build and publish
117-
needs: build-dylib
144+
needs: [build-dylib, check-perms]
118145
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
119146
permissions:
120147
# Required to publish a release

cli/schedule.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ When enabling scheduled stop, enter a duration in one of the following formats:
4646
* 2m (2 minutes)
4747
* 2 (2 minutes)
4848
`
49-
scheduleExtendDescriptionLong = `
49+
scheduleExtendDescriptionLong = `Extends the workspace deadline.
5050
* The new stop time is calculated from *now*.
5151
* The new stop time must be at least 30 minutes in the future.
5252
* The workspace template may restrict the maximum workspace runtime.
@@ -157,6 +157,13 @@ func (r *RootCmd) scheduleStart() *serpent.Command {
157157
return err
158158
}
159159

160+
// Autostart configuration is not supported for prebuilt workspaces.
161+
// Prebuild lifecycle is managed by the reconciliation loop, with scheduling behavior
162+
// defined per preset at the template level, not per workspace.
163+
if workspace.IsPrebuild {
164+
return xerrors.Errorf("autostart configuration is not supported for prebuilt workspaces")
165+
}
166+
160167
var schedStr *string
161168
if inv.Args[1] != "manual" {
162169
sched, err := parseCLISchedule(inv.Args[1:]...)
@@ -205,6 +212,13 @@ func (r *RootCmd) scheduleStop() *serpent.Command {
205212
return err
206213
}
207214

215+
// Autostop configuration is not supported for prebuilt workspaces.
216+
// Prebuild lifecycle is managed by the reconciliation loop, with scheduling behavior
217+
// defined per preset at the template level, not per workspace.
218+
if workspace.IsPrebuild {
219+
return xerrors.Errorf("autostop configuration is not supported for prebuilt workspaces")
220+
}
221+
208222
var durMillis *int64
209223
if inv.Args[1] != "manual" {
210224
dur, err := parseDuration(inv.Args[1])
@@ -255,6 +269,13 @@ func (r *RootCmd) scheduleExtend() *serpent.Command {
255269
return xerrors.Errorf("get workspace: %w", err)
256270
}
257271

272+
// Deadline extensions are not supported for prebuilt workspaces.
273+
// Prebuild lifecycle is managed by the reconciliation loop, with TTL behavior
274+
// defined per preset at the template level, not per workspace.
275+
if workspace.IsPrebuild {
276+
return xerrors.Errorf("extend configuration is not supported for prebuilt workspaces")
277+
}
278+
258279
loc, err := tz.TimezoneIANA()
259280
if err != nil {
260281
loc = time.UTC // best effort

cli/templateedit.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ func (r *RootCmd) templateEdit() *serpent.Command {
169169

170170
req := codersdk.UpdateTemplateMeta{
171171
Name: name,
172-
DisplayName: displayName,
173-
Description: description,
174-
Icon: icon,
172+
DisplayName: &displayName,
173+
Description: &description,
174+
Icon: &icon,
175175
DefaultTTLMillis: defaultTTL.Milliseconds(),
176176
ActivityBumpMillis: activityBump.Milliseconds(),
177177
AutostopRequirement: &codersdk.TemplateAutostopRequirement{

cli/testdata/coder_schedule_extend_--help.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ USAGE:
77

88
Aliases: override-stop
99

10-
* The new stop time is calculated from *now*.
10+
Extends the workspace deadline.
11+
* The new stop time is calculated from *now*.
1112
* The new stop time must be at least 30 minutes in the future.
1213
* The workspace template may restrict the maximum workspace runtime.
1314

coderd/autobuild/lifecycle_executor_test.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,15 +1251,23 @@ func TestExecutorPrebuilds(t *testing.T) {
12511251
}()
12521252

12531253
// Then: the prebuilt workspace should remain in a start transition
1254-
prebuildStats := <-statsCh
1254+
prebuildStats := testutil.RequireReceive(ctx, t, statsCh)
12551255
require.Len(t, prebuildStats.Errors, 0)
12561256
require.Len(t, prebuildStats.Transitions, 0)
12571257
require.Equal(t, codersdk.WorkspaceTransitionStart, prebuild.LatestBuild.Transition)
12581258
prebuild = coderdtest.MustWorkspace(t, client, prebuild.ID)
12591259
require.Equal(t, codersdk.BuildReasonInitiator, prebuild.LatestBuild.Reason)
12601260

12611261
// Given: a user claims the prebuilt workspace
1262-
dbWorkspace := dbgen.ClaimPrebuild(t, db, user.ID, "claimedWorkspace-autostop", preset.ID)
1262+
dbWorkspace := dbgen.ClaimPrebuild(
1263+
t, db,
1264+
clock.Now(),
1265+
user.ID,
1266+
"claimedWorkspace-autostop",
1267+
preset.ID,
1268+
sql.NullString{},
1269+
sql.NullTime{},
1270+
sql.NullInt64{})
12631271
workspace := coderdtest.MustWorkspace(t, client, dbWorkspace.ID)
12641272

12651273
// When: the autobuild executor ticks *after* the deadline:
@@ -1269,7 +1277,7 @@ func TestExecutorPrebuilds(t *testing.T) {
12691277
}()
12701278

12711279
// Then: the workspace should be stopped
1272-
workspaceStats := <-statsCh
1280+
workspaceStats := testutil.RequireReceive(ctx, t, statsCh)
12731281
require.Len(t, workspaceStats.Errors, 0)
12741282
require.Len(t, workspaceStats.Transitions, 1)
12751283
require.Contains(t, workspaceStats.Transitions, workspace.ID)
@@ -1336,7 +1344,7 @@ func TestExecutorPrebuilds(t *testing.T) {
13361344
}()
13371345

13381346
// Then: the prebuilt workspace should remain in a stop transition
1339-
prebuildStats := <-statsCh
1347+
prebuildStats := testutil.RequireReceive(ctx, t, statsCh)
13401348
require.Len(t, prebuildStats.Errors, 0)
13411349
require.Len(t, prebuildStats.Transitions, 0)
13421350
require.Equal(t, codersdk.WorkspaceTransitionStop, prebuild.LatestBuild.Transition)
@@ -1353,7 +1361,15 @@ func TestExecutorPrebuilds(t *testing.T) {
13531361
database.WorkspaceTransitionStart)
13541362

13551363
// Given: a user claims the prebuilt workspace
1356-
dbWorkspace := dbgen.ClaimPrebuild(t, db, user.ID, "claimedWorkspace-autostart", preset.ID)
1364+
dbWorkspace := dbgen.ClaimPrebuild(
1365+
t, db,
1366+
clock.Now(),
1367+
user.ID,
1368+
"claimedWorkspace-autostart",
1369+
preset.ID,
1370+
autostartSched,
1371+
sql.NullTime{},
1372+
sql.NullInt64{})
13571373
workspace := coderdtest.MustWorkspace(t, client, dbWorkspace.ID)
13581374

13591375
// Given: the prebuilt workspace goes to a stop status
@@ -1374,7 +1390,7 @@ func TestExecutorPrebuilds(t *testing.T) {
13741390
}()
13751391

13761392
// Then: the workspace should eventually be started
1377-
workspaceStats := <-statsCh
1393+
workspaceStats := testutil.RequireReceive(ctx, t, statsCh)
13781394
require.Len(t, workspaceStats.Errors, 0)
13791395
require.Len(t, workspaceStats.Transitions, 1)
13801396
require.Contains(t, workspaceStats.Transitions, workspace.ID)
@@ -1486,8 +1502,8 @@ func setupTestDBWorkspaceBuild(
14861502
Architecture: "i386",
14871503
OperatingSystem: "linux",
14881504
LifecycleState: database.WorkspaceAgentLifecycleStateReady,
1489-
StartedAt: sql.NullTime{Time: time.Now().Add(time.Hour), Valid: true},
1490-
ReadyAt: sql.NullTime{Time: time.Now().Add(-1 * time.Hour), Valid: true},
1505+
StartedAt: sql.NullTime{Time: clock.Now().Add(time.Hour), Valid: true},
1506+
ReadyAt: sql.NullTime{Time: clock.Now().Add(-1 * time.Hour), Valid: true},
14911507
APIKeyScope: database.AgentKeyScopeEnumAll,
14921508
})
14931509

@@ -1524,8 +1540,9 @@ func setupTestDBPrebuiltWorkspace(
15241540
OrganizationID: orgID,
15251541
OwnerID: database.PrebuildsSystemUserID,
15261542
Deleted: false,
1527-
CreatedAt: time.Now().Add(-time.Hour * 2),
1543+
CreatedAt: clock.Now().Add(-time.Hour * 2),
15281544
AutostartSchedule: options.AutostartSchedule,
1545+
LastUsedAt: clock.Now(),
15291546
})
15301547
setupTestDBWorkspaceBuild(ctx, t, clock, db, ps, orgID, workspace.ID, templateVersionID, presetID, buildTransition)
15311548

0 commit comments

Comments
 (0)