Skip to content

Commit 7fd13df

Browse files
authored
Merge branch 'main' into mafredri/feat-coderd-add-user-latency-and-insights-endpoints
2 parents fc2157d + 1a915f5 commit 7fd13df

37 files changed

+459
-209
lines changed

.github/dependabot.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,28 @@ updates:
123123
- "@swc/jest"
124124
- "@types/jest"
125125

126+
- package-ecosystem: "npm"
127+
directory: "/offlinedocs/"
128+
schedule:
129+
interval: "monthly"
130+
time: "06:00"
131+
timezone: "America/Chicago"
132+
reviewers:
133+
- "coder/ts"
134+
commit-message:
135+
prefix: "chore"
136+
labels: []
137+
ignore:
138+
# Ignore patch updates for all dependencies
139+
- dependency-name: "*"
140+
update-types:
141+
- version-update:semver-patch
142+
# Ignore major updates to Node.js types, because they need to
143+
# correspond to the Node.js engine version
144+
- dependency-name: "@types/node"
145+
update-types:
146+
- version-update:semver-major
147+
126148
# Update dogfood.
127149
- package-ecosystem: "docker"
128150
directory: "/dogfood/"

.github/workflows/ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ jobs:
8585
ts:
8686
- "site/**"
8787
- "Makefile"
88+
- "offlinedocs/**"
8889
k8s:
8990
- "helm/**"
9091
- "scripts/Dockerfile"

.github/workflows/release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ jobs:
7676
set -euo pipefail
7777
ref=HEAD
7878
old_version="$(git describe --abbrev=0 "$ref^1")"
79-
version="$(./scripts/version.sh)"
79+
version="v$(./scripts/version.sh)"
8080
8181
# Generate notes.
8282
release_notes_file="$(mktemp -t release_notes.XXXXXX)"

cli/clistat/cgroup.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ func readInt64Prefix(fs afero.Fs, path, prefix string) (int64, error) {
338338

339339
scn := bufio.NewScanner(bytes.NewReader(data))
340340
for scn.Scan() {
341-
line := scn.Text()
341+
line := strings.TrimSpace(scn.Text())
342342
if !strings.HasPrefix(line, prefix) {
343343
continue
344344
}

cli/clistat/container.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import (
1010
)
1111

1212
const (
13-
procMounts = "/proc/mounts"
14-
procOneCgroup = "/proc/1/cgroup"
13+
procMounts = "/proc/mounts"
14+
procOneCgroup = "/proc/1/cgroup"
15+
kubernetesDefaultServiceAccountToken = "/var/run/secrets/kubernetes.io/serviceaccount/token" //nolint:gosec
1516
)
1617

1718
// IsContainerized returns whether the host is containerized.
@@ -38,6 +39,14 @@ func IsContainerized(fs afero.Fs) (ok bool, err error) {
3839
}
3940
}
4041

42+
// Sometimes the above method of sniffing /proc/1/cgroup isn't reliable.
43+
// If a Kubernetes service account token is present, that's
44+
// also a good indication that we are in a container.
45+
_, err = afero.ReadFile(fs, kubernetesDefaultServiceAccountToken)
46+
if err == nil {
47+
return true, nil
48+
}
49+
4150
// Last-ditch effort to detect Sysbox containers.
4251
// Check if we have anything mounted as type sysboxfs in /proc/mounts
4352
mountsData, err := afero.ReadFile(fs, procMounts)

cli/templateedit_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ func TestTemplateEdit(t *testing.T) {
409409
clitest.SetupConfig(t, proxyClient, root)
410410

411411
ctx := testutil.Context(t, testutil.WaitLong)
412-
err = inv.WithContext(ctx).Run()
412+
err := inv.WithContext(ctx).Run()
413413
if c.ok {
414414
require.NoError(t, err)
415415
} else {

coderd/autobuild/lifecycle_executor.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (e *Executor) runOnce(t time.Time) Stats {
178178
// Lock the workspace if it has breached the template's
179179
// threshold for inactivity.
180180
if reason == database.BuildReasonAutolock {
181-
err = tx.UpdateWorkspaceLockedAt(e.ctx, database.UpdateWorkspaceLockedAtParams{
181+
err = tx.UpdateWorkspaceLockedDeletingAt(e.ctx, database.UpdateWorkspaceLockedDeletingAtParams{
182182
ID: ws.ID,
183183
LockedAt: sql.NullTime{
184184
Time: database.Now(),
@@ -347,11 +347,11 @@ func isEligibleForLockedStop(ws database.Workspace, templateSchedule schedule.Te
347347

348348
func isEligibleForDelete(ws database.Workspace, templateSchedule schedule.TemplateScheduleOptions, currentTick time.Time) bool {
349349
// Only attempt to delete locked workspaces.
350-
return ws.LockedAt.Valid &&
350+
return ws.LockedAt.Valid && ws.DeletingAt.Valid &&
351351
// Locked workspaces should only be deleted if a locked_ttl is specified.
352352
templateSchedule.LockedTTL > 0 &&
353353
// The workspace must breach the locked_ttl.
354-
currentTick.Sub(ws.LockedAt.Time) > templateSchedule.LockedTTL
354+
currentTick.After(ws.DeletingAt.Time)
355355
}
356356

357357
// isEligibleForFailedStop returns true if the workspace is eligible to be stopped

coderd/database/dbauthz/dbauthz.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,11 +2511,11 @@ func (q *querier) UpdateWorkspaceLastUsedAt(ctx context.Context, arg database.Up
25112511
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLastUsedAt)(ctx, arg)
25122512
}
25132513

2514-
func (q *querier) UpdateWorkspaceLockedAt(ctx context.Context, arg database.UpdateWorkspaceLockedAtParams) error {
2515-
fetch := func(ctx context.Context, arg database.UpdateWorkspaceLockedAtParams) (database.Workspace, error) {
2514+
func (q *querier) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) error {
2515+
fetch := func(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) (database.Workspace, error) {
25162516
return q.db.GetWorkspaceByID(ctx, arg.ID)
25172517
}
2518-
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLockedAt)(ctx, arg)
2518+
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLockedDeletingAt)(ctx, arg)
25192519
}
25202520

25212521
func (q *querier) UpdateWorkspaceProxy(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
@@ -2539,6 +2539,14 @@ func (q *querier) UpdateWorkspaceTTL(ctx context.Context, arg database.UpdateWor
25392539
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceTTL)(ctx, arg)
25402540
}
25412541

2542+
func (q *querier) UpdateWorkspacesDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDeletingAtByTemplateIDParams) error {
2543+
fetch := func(ctx context.Context, arg database.UpdateWorkspacesDeletingAtByTemplateIDParams) (database.Template, error) {
2544+
return q.db.GetTemplateByID(ctx, arg.TemplateID)
2545+
}
2546+
2547+
return fetchAndExec(q.log, q.auth, rbac.ActionUpdate, fetch, q.db.UpdateWorkspacesDeletingAtByTemplateID)(ctx, arg)
2548+
}
2549+
25422550
func (q *querier) UpsertAppSecurityKey(ctx context.Context, data string) error {
25432551
// No authz checks as this is done during startup
25442552
return q.db.UpsertAppSecurityKey(ctx, data)

coderd/database/dbfake/dbfake.go

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspac
339339
AutostartSchedule: w.AutostartSchedule,
340340
Ttl: w.Ttl,
341341
LastUsedAt: w.LastUsedAt,
342+
LockedAt: w.LockedAt,
343+
DeletingAt: w.DeletingAt,
342344
Count: count,
343345
}
344346

@@ -5042,24 +5044,42 @@ func (q *FakeQuerier) UpdateWorkspaceLastUsedAt(_ context.Context, arg database.
50425044
return sql.ErrNoRows
50435045
}
50445046

5045-
func (q *FakeQuerier) UpdateWorkspaceLockedAt(_ context.Context, arg database.UpdateWorkspaceLockedAtParams) error {
5047+
func (q *FakeQuerier) UpdateWorkspaceLockedDeletingAt(_ context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) error {
50465048
if err := validateDatabaseType(arg); err != nil {
50475049
return err
50485050
}
5049-
50505051
q.mutex.Lock()
50515052
defer q.mutex.Unlock()
5052-
50535053
for index, workspace := range q.workspaces {
50545054
if workspace.ID != arg.ID {
50555055
continue
50565056
}
50575057
workspace.LockedAt = arg.LockedAt
5058-
workspace.LastUsedAt = database.Now()
5058+
if workspace.LockedAt.Time.IsZero() {
5059+
workspace.LastUsedAt = database.Now()
5060+
workspace.DeletingAt = sql.NullTime{}
5061+
}
5062+
if !workspace.LockedAt.Time.IsZero() {
5063+
var template database.TemplateTable
5064+
for _, t := range q.templates {
5065+
if t.ID == workspace.TemplateID {
5066+
template = t
5067+
break
5068+
}
5069+
}
5070+
if template.ID == uuid.Nil {
5071+
return xerrors.Errorf("unable to find workspace template")
5072+
}
5073+
if template.LockedTTL > 0 {
5074+
workspace.DeletingAt = sql.NullTime{
5075+
Valid: true,
5076+
Time: workspace.LockedAt.Time.Add(time.Duration(template.LockedTTL)),
5077+
}
5078+
}
5079+
}
50595080
q.workspaces[index] = workspace
50605081
return nil
50615082
}
5062-
50635083
return sql.ErrNoRows
50645084
}
50655085

@@ -5123,6 +5143,32 @@ func (q *FakeQuerier) UpdateWorkspaceTTL(_ context.Context, arg database.UpdateW
51235143
return sql.ErrNoRows
51245144
}
51255145

5146+
func (q *FakeQuerier) UpdateWorkspacesDeletingAtByTemplateID(_ context.Context, arg database.UpdateWorkspacesDeletingAtByTemplateIDParams) error {
5147+
q.mutex.Lock()
5148+
defer q.mutex.Unlock()
5149+
5150+
err := validateDatabaseType(arg)
5151+
if err != nil {
5152+
return err
5153+
}
5154+
5155+
for i, ws := range q.workspaces {
5156+
if ws.LockedAt.Time.IsZero() {
5157+
continue
5158+
}
5159+
deletingAt := sql.NullTime{
5160+
Valid: arg.LockedTtlMs > 0,
5161+
}
5162+
if arg.LockedTtlMs > 0 {
5163+
deletingAt.Time = ws.LockedAt.Time.Add(time.Duration(arg.LockedTtlMs) * time.Millisecond)
5164+
}
5165+
ws.DeletingAt = deletingAt
5166+
q.workspaces[i] = ws
5167+
}
5168+
5169+
return nil
5170+
}
5171+
51265172
func (q *FakeQuerier) UpsertAppSecurityKey(_ context.Context, data string) error {
51275173
q.mutex.Lock()
51285174
defer q.mutex.Unlock()

coderd/database/dbmetrics/dbmetrics.go

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

coderd/database/dbmock/dbmock.go

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

coderd/database/dump.sql

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE workspaces DROP COLUMN deleting_at;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE workspaces ADD COLUMN deleting_at timestamptz NULL;

coderd/database/modelmethods.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ func ConvertWorkspaceRows(rows []GetWorkspacesRow) []Workspace {
354354
AutostartSchedule: r.AutostartSchedule,
355355
Ttl: r.Ttl,
356356
LastUsedAt: r.LastUsedAt,
357+
LockedAt: r.LockedAt,
358+
DeletingAt: r.DeletingAt,
357359
}
358360
}
359361

coderd/database/modelqueries.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
240240
&i.Ttl,
241241
&i.LastUsedAt,
242242
&i.LockedAt,
243+
&i.DeletingAt,
243244
&i.TemplateName,
244245
&i.TemplateVersionID,
245246
&i.TemplateVersionName,

coderd/database/models.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/querier.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)