Skip to content

Commit 9baecf9

Browse files
authored
Merge branch 'main' into depot-runners
2 parents 12553e3 + 313d4e0 commit 9baecf9

34 files changed

+1717
-223
lines changed

.github/actions/setup-go/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: |
44
inputs:
55
version:
66
description: "The Go version to use."
7-
default: "1.22.3"
7+
default: "1.22.4"
88
runs:
99
using: "composite"
1010
steps:

.github/workflows/ci.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,9 @@ jobs:
254254
- name: Setup Node
255255
uses: ./.github/actions/setup-node
256256

257+
# Use default Go version
257258
- name: Setup Go
258-
uses: actions/setup-go@v5
259-
with:
260-
# This doesn't need caching. It's super fast anyways!
261-
cache: false
262-
go-version: 1.21.9
259+
uses: ./.github/actions/setup-go
263260

264261
- name: Install shfmt
265262
run: go install mvdan.cc/sh/v3/cmd/shfmt@v3.7.0

cli/login.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,13 @@ func (r *RootCmd) login() *serpent.Command {
336336
return xerrors.Errorf("write server url: %w", err)
337337
}
338338

339+
// If the current organization cannot be fetched, then reset the organization context.
340+
// Otherwise, organization cli commands will fail.
341+
_, err = CurrentOrganization(r, inv, client)
342+
if err != nil {
343+
_ = config.Organization().Delete()
344+
}
345+
339346
_, _ = fmt.Fprintf(inv.Stdout, Caret+"Welcome to Coder, %s! You're authenticated.\n", pretty.Sprint(cliui.DefaultStyles.Keyword, resp.Username))
340347
return nil
341348
},

cli/login_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import (
55
"fmt"
66
"net/http"
77
"net/http/httptest"
8+
"os"
89
"runtime"
910
"testing"
1011

12+
"github.com/google/uuid"
1113
"github.com/stretchr/testify/assert"
1214
"github.com/stretchr/testify/require"
1315

@@ -304,4 +306,48 @@ func TestLogin(t *testing.T) {
304306
// This **should not be equal** to the token we passed in.
305307
require.NotEqual(t, client.SessionToken(), sessionFile)
306308
})
309+
310+
// Login should reset the configured organization if the user is not a member
311+
t.Run("ResetOrganization", func(t *testing.T) {
312+
t.Parallel()
313+
client := coderdtest.New(t, nil)
314+
coderdtest.CreateFirstUser(t, client)
315+
root, cfg := clitest.New(t, "login", client.URL.String(), "--token", client.SessionToken())
316+
317+
notRealOrg := uuid.NewString()
318+
err := cfg.Organization().Write(notRealOrg)
319+
require.NoError(t, err, "write bad org to config")
320+
321+
err = root.Run()
322+
require.NoError(t, err)
323+
sessionFile, err := cfg.Session().Read()
324+
require.NoError(t, err)
325+
require.NotEqual(t, client.SessionToken(), sessionFile)
326+
327+
// Organization config should be deleted since the org does not exist
328+
selected, err := cfg.Organization().Read()
329+
require.ErrorIs(t, err, os.ErrNotExist)
330+
require.NotEqual(t, selected, notRealOrg)
331+
})
332+
333+
t.Run("KeepOrganizationContext", func(t *testing.T) {
334+
t.Parallel()
335+
client := coderdtest.New(t, nil)
336+
first := coderdtest.CreateFirstUser(t, client)
337+
root, cfg := clitest.New(t, "login", client.URL.String(), "--token", client.SessionToken())
338+
339+
err := cfg.Organization().Write(first.OrganizationID.String())
340+
require.NoError(t, err, "write bad org to config")
341+
342+
err = root.Run()
343+
require.NoError(t, err)
344+
sessionFile, err := cfg.Session().Read()
345+
require.NoError(t, err)
346+
require.NotEqual(t, client.SessionToken(), sessionFile)
347+
348+
// Organization config should be deleted since the org does not exist
349+
selected, err := cfg.Organization().Read()
350+
require.NoError(t, err)
351+
require.Equal(t, selected, first.OrganizationID.String())
352+
})
307353
}

coderd/audit/diff.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ type Auditable interface {
2222
database.HealthSettings |
2323
database.OAuth2ProviderApp |
2424
database.OAuth2ProviderAppSecret |
25-
database.CustomRole
25+
database.CustomRole |
26+
database.AuditableOrganizationMember
2627
}
2728

2829
// Map is a map of changed fields in an audited resource. It maps field names to

coderd/audit/request.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ func ResourceTarget[T Auditable](tgt T) string {
105105
return typed.DisplaySecret
106106
case database.CustomRole:
107107
return typed.Name
108+
case database.AuditableOrganizationMember:
109+
return typed.Username
108110
default:
109111
panic(fmt.Sprintf("unknown resource %T for ResourceTarget", tgt))
110112
}
@@ -144,6 +146,8 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
144146
return typed.ID
145147
case database.CustomRole:
146148
return typed.ID
149+
case database.AuditableOrganizationMember:
150+
return typed.UserID
147151
default:
148152
panic(fmt.Sprintf("unknown resource %T for ResourceID", tgt))
149153
}
@@ -181,6 +185,8 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
181185
return database.ResourceTypeOauth2ProviderAppSecret
182186
case database.CustomRole:
183187
return database.ResourceTypeCustomRole
188+
case database.AuditableOrganizationMember:
189+
return database.ResourceTypeOrganizationMember
184190
default:
185191
panic(fmt.Sprintf("unknown resource %T for ResourceType", typed))
186192
}
@@ -219,6 +225,8 @@ func ResourceRequiresOrgID[T Auditable]() bool {
219225
return false
220226
case database.CustomRole:
221227
return true
228+
case database.AuditableOrganizationMember:
229+
return true
222230
default:
223231
panic(fmt.Sprintf("unknown resource %T for ResourceRequiresOrgID", tgt))
224232
}

coderd/coderdtest/coderdtest.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,18 @@ func NewTaggedProvisionerDaemon(t testing.TB, coderAPI *coderd.API, name string,
600600
}
601601

602602
func NewExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uuid.UUID, tags map[string]string) io.Closer {
603+
t.Helper()
604+
605+
// Without this check, the provisioner will silently fail.
606+
entitlements, err := client.Entitlements(context.Background())
607+
if err == nil {
608+
feature := entitlements.Features[codersdk.FeatureExternalProvisionerDaemons]
609+
if !feature.Enabled || feature.Entitlement != codersdk.EntitlementEntitled {
610+
require.NoError(t, xerrors.Errorf("external provisioner daemons require an entitled license"))
611+
return nil
612+
}
613+
}
614+
603615
echoClient, echoServer := drpc.MemTransportPipe()
604616
ctx, cancelFunc := context.WithCancel(context.Background())
605617
serveDone := make(chan struct{})
@@ -638,6 +650,7 @@ func NewExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uui
638650
t.Cleanup(func() {
639651
_ = closer.Close()
640652
})
653+
641654
return closer
642655
}
643656

@@ -790,6 +803,37 @@ func createAnotherUserRetry(t testing.TB, client *codersdk.Client, organizationI
790803
return other, user
791804
}
792805

806+
type CreateOrganizationOptions struct {
807+
// IncludeProvisionerDaemon will spin up an external provisioner for the organization.
808+
// This requires enterprise and the feature 'codersdk.FeatureExternalProvisionerDaemons'
809+
IncludeProvisionerDaemon bool
810+
}
811+
812+
func CreateOrganization(t *testing.T, client *codersdk.Client, opts CreateOrganizationOptions, mutators ...func(*codersdk.CreateOrganizationRequest)) codersdk.Organization {
813+
ctx := testutil.Context(t, testutil.WaitMedium)
814+
req := codersdk.CreateOrganizationRequest{
815+
Name: strings.ReplaceAll(strings.ToLower(namesgenerator.GetRandomName(0)), "_", "-"),
816+
DisplayName: namesgenerator.GetRandomName(1),
817+
Description: namesgenerator.GetRandomName(1),
818+
Icon: "",
819+
}
820+
for _, mutator := range mutators {
821+
mutator(&req)
822+
}
823+
824+
org, err := client.CreateOrganization(ctx, req)
825+
require.NoError(t, err)
826+
827+
if opts.IncludeProvisionerDaemon {
828+
closer := NewExternalProvisionerDaemon(t, client, org.ID, map[string]string{})
829+
t.Cleanup(func() {
830+
_ = closer.Close()
831+
})
832+
}
833+
834+
return org
835+
}
836+
793837
// CreateTemplateVersion creates a template import provisioner job
794838
// with the responses provided. It uses the "echo" provisioner for compatibility
795839
// with testing.

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.

coderd/database/migrations/000220_audit_org_member.down.sql

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'organization_member';

0 commit comments

Comments
 (0)