mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: move aibridge library code into coder repo (#24190)
This PR merges code from `coder/aibridge` repository into `coder/coder`. It was split into 4 PRs for easier review but stacked PRs will need to be merged into this PR so all checks pass. * https://github.com/coder/coder/pull/24190 -> raw code copy (this PR, before merging PRs on top of it, it was just 1 commit: https://github.com/coder/coder/commit/70d33f33200c7e77df910957595715f81f9bec24) * https://github.com/coder/coder/pull/24570 -> update imports in `coder/coder` to use copied code * https://github.com/coder/coder/pull/24586 -> linter fixes and CI integration (also added README.md) * https://github.com/coder/coder/pull/24571 -> added exclude to scripts/check_emdash.sh check Original PR message (before PR squash): Moves coder/aibridge code into coder/coder repository. Omitted files: - `go.mod`, `go.sum`, `.gitignore`, `.github/workflows/ci.yml,` `Makefile`, `LICENSE`, `README.md` (modified README.md is added later) - `.github`, `example`, `buildinfo,` `scripts` directories Simple verification script (will list omitted files) ``` tmp=$(mktemp -d) echo "$tmp" git clone --depth=1 https://github.com/coder/aibridge "$tmp/aibridge" git clone --depth=1 --branch pb/aibridge-code-move https://github.com/coder/coder "$tmp/coder" diff -rq --exclude=.git "$tmp/aibridge" "$tmp/coder/aibridge" # rm -rf "$tmp" ```
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package utils
|
||||
|
||||
import "strings"
|
||||
|
||||
// ExtractBearerToken extracts the token from a "Bearer <token>" authorization header.
|
||||
func ExtractBearerToken(auth string) string {
|
||||
if auth := strings.TrimSpace(auth); auth != "" {
|
||||
fields := strings.Fields(auth)
|
||||
if len(fields) == 2 && strings.EqualFold(fields[0], "Bearer") {
|
||||
return fields[1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/coder/coder/v2/aibridge/utils"
|
||||
)
|
||||
|
||||
func TestExtractBearerToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "Empty",
|
||||
input: "",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "Whitespace",
|
||||
input: " ",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "InvalidFormat",
|
||||
input: "some-token",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "BearerOnly",
|
||||
input: "Bearer",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "Valid",
|
||||
input: "Bearer my-secret-token",
|
||||
expected: "my-secret-token",
|
||||
},
|
||||
{
|
||||
name: "BearerMixedCase",
|
||||
input: "BeArEr my-secret-token",
|
||||
expected: "my-secret-token",
|
||||
},
|
||||
{
|
||||
name: "LeadingWhitespace",
|
||||
input: " Bearer my-secret-token",
|
||||
expected: "my-secret-token",
|
||||
},
|
||||
{
|
||||
name: "TrailingWhitespace",
|
||||
input: "Bearer my-secret-token ",
|
||||
expected: "my-secret-token",
|
||||
},
|
||||
{
|
||||
name: "TooManyParts",
|
||||
input: "Bearer token extra",
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
result := utils.ExtractBearerToken(tt.input)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
)
|
||||
|
||||
// ConcurrentGroup is like errgroup.Group but differs in that an error in one
|
||||
// goroutine will not interrupt the functioning of another.
|
||||
// See https://pkg.go.dev/golang.org/x/sync/errgroup#Group.Go.
|
||||
type ConcurrentGroup struct {
|
||||
wg sync.WaitGroup
|
||||
|
||||
errsMu sync.Mutex
|
||||
errs error
|
||||
}
|
||||
|
||||
func NewConcurrentGroup() *ConcurrentGroup {
|
||||
return &ConcurrentGroup{}
|
||||
}
|
||||
|
||||
func (c *ConcurrentGroup) Go(fn func() error) {
|
||||
c.wg.Add(1)
|
||||
go func() {
|
||||
defer c.wg.Done()
|
||||
if err := fn(); err != nil {
|
||||
c.errsMu.Lock()
|
||||
c.errs = multierror.Append(c.errs, err)
|
||||
c.errsMu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *ConcurrentGroup) Wait() error {
|
||||
c.wg.Wait()
|
||||
return c.errs
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/aibridge/utils"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
goleak.VerifyTestMain(m)
|
||||
}
|
||||
|
||||
func TestConcurrentGroup(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("no goroutines", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cg := utils.NewConcurrentGroup()
|
||||
require.NoError(t, cg.Wait())
|
||||
})
|
||||
|
||||
t.Run("multiple goroutines, all ok", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cg := utils.NewConcurrentGroup()
|
||||
cg.Go(func() error {
|
||||
return nil
|
||||
})
|
||||
cg.Go(func() error {
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, cg.Wait())
|
||||
})
|
||||
|
||||
t.Run("multiple goroutines, one err", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cg := utils.NewConcurrentGroup()
|
||||
oops := xerrors.New("oops")
|
||||
cg.Go(func() error {
|
||||
return oops
|
||||
})
|
||||
cg.Go(func() error {
|
||||
return nil
|
||||
})
|
||||
require.ErrorIs(t, cg.Wait(), oops)
|
||||
})
|
||||
|
||||
t.Run("multiple goroutines, multiple errs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cg := utils.NewConcurrentGroup()
|
||||
oops := xerrors.New("oops")
|
||||
eek := xerrors.New("eek")
|
||||
cg.Go(func() error {
|
||||
return oops
|
||||
})
|
||||
cg.Go(func() error {
|
||||
return eek
|
||||
})
|
||||
|
||||
errs := cg.Wait()
|
||||
require.ErrorIs(t, errs, oops)
|
||||
require.ErrorIs(t, errs, eek)
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkConcurrentGroup(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
cg := utils.NewConcurrentGroup()
|
||||
for j := 0; j < 10; j++ {
|
||||
cg.Go(func() error { return nil })
|
||||
}
|
||||
_ = cg.Wait()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package utils
|
||||
|
||||
// MaskSecret masks the middle of a secret string, revealing a small
|
||||
// prefix and suffix for identification. The number of characters
|
||||
// revealed scales with string length.
|
||||
func MaskSecret(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
runes := []rune(s)
|
||||
reveal := revealLength(len(runes))
|
||||
|
||||
if len(runes) <= reveal*2 {
|
||||
return "..."
|
||||
}
|
||||
|
||||
prefix := string(runes[:reveal])
|
||||
suffix := string(runes[len(runes)-reveal:])
|
||||
return prefix + "..." + suffix
|
||||
}
|
||||
|
||||
// revealLength returns the number of runes to show at each end.
|
||||
func revealLength(n int) int {
|
||||
switch {
|
||||
case n >= 20:
|
||||
return 4
|
||||
case n >= 10:
|
||||
return 2
|
||||
case n >= 5:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/coder/coder/v2/aibridge/utils"
|
||||
)
|
||||
|
||||
func TestMaskSecret(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{"empty", "", ""},
|
||||
{"single_char", "x", "..."},
|
||||
{"two_chars", "ab", "..."},
|
||||
{"four_chars", "abcd", "..."},
|
||||
{"short", "short", "s...t"},
|
||||
{"short_9_chars", "veryshort", "v...t"},
|
||||
{"medium_15_chars", "thisisquitelong", "th...ng"},
|
||||
{"long_api_key", "sk-ant-api03-abcdefgh", "sk-a...efgh"},
|
||||
{"unicode", "hélloworld🌍!", "hé...🌍!"},
|
||||
{"github_token", "ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh", "ghp_...efgh"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, tc.expected, utils.MaskSecret(tc.input))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package utils
|
||||
|
||||
// PtrTo returns a reference to v.
|
||||
func PtrTo[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
Reference in New Issue
Block a user