fix: make default support links respect --docs-url (#14176)

make default support links respect --docs-url
This commit is contained in:
Benjamin Peinhardt
2024-08-12 17:01:22 -04:00
committed by GitHub
parent 4c7132f08b
commit 76722a7db5
7 changed files with 80 additions and 44 deletions
+42 -25
View File
@@ -2,7 +2,10 @@ package appearance
import (
"context"
"fmt"
"strings"
"github.com/coder/coder/v2/buildinfo"
"github.com/coder/coder/v2/codersdk"
)
@@ -10,36 +13,50 @@ type Fetcher interface {
Fetch(ctx context.Context) (codersdk.AppearanceConfig, error)
}
var DefaultSupportLinks = []codersdk.LinkConfig{
{
Name: "Documentation",
Target: "https://coder.com/docs/coder-oss",
Icon: "docs",
},
{
Name: "Report a bug",
Target: "https://github.com/coder/coder/issues/new?labels=needs+grooming&body={CODER_BUILD_INFO}",
Icon: "bug",
},
{
Name: "Join the Coder Discord",
Target: "https://coder.com/chat?utm_source=coder&utm_medium=coder&utm_campaign=server-footer",
Icon: "chat",
},
{
Name: "Star the Repo",
Target: "https://github.com/coder/coder",
Icon: "star",
},
func DefaultSupportLinks(docsURL string) []codersdk.LinkConfig {
version := buildinfo.Version()
if docsURL == "" {
docsURL = "https://coder.com/docs/@" + strings.Split(version, "-")[0]
}
buildInfo := fmt.Sprintf("Version: [`%s`](%s)", version, buildinfo.ExternalURL())
return []codersdk.LinkConfig{
{
Name: "Documentation",
Target: docsURL,
Icon: "docs",
},
{
Name: "Report a bug",
Target: "https://github.com/coder/coder/issues/new?labels=needs+grooming&body=" + buildInfo,
Icon: "bug",
},
{
Name: "Join the Coder Discord",
Target: "https://coder.com/chat?utm_source=coder&utm_medium=coder&utm_campaign=server-footer",
Icon: "chat",
},
{
Name: "Star the Repo",
Target: "https://github.com/coder/coder",
Icon: "star",
},
}
}
type AGPLFetcher struct{}
type AGPLFetcher struct {
docsURL string
}
func (AGPLFetcher) Fetch(context.Context) (codersdk.AppearanceConfig, error) {
func (f AGPLFetcher) Fetch(context.Context) (codersdk.AppearanceConfig, error) {
return codersdk.AppearanceConfig{
AnnouncementBanners: []codersdk.BannerConfig{},
SupportLinks: DefaultSupportLinks,
SupportLinks: DefaultSupportLinks(f.docsURL),
}, nil
}
var DefaultFetcher Fetcher = AGPLFetcher{}
func NewDefaultFetcher(docsURL string) Fetcher {
return &AGPLFetcher{
docsURL: docsURL,
}
}
+2 -1
View File
@@ -475,7 +475,8 @@ func New(options *Options) *API {
dbRolluper: options.DatabaseRolluper,
}
api.AppearanceFetcher.Store(&appearance.DefaultFetcher)
f := appearance.NewDefaultFetcher(api.DeploymentValues.DocsURL.String())
api.AppearanceFetcher.Store(&f)
api.PortSharer.Store(&portsharing.DefaultPortSharer)
buildInfo := codersdk.BuildInfoResponse{
ExternalURL: buildinfo.ExternalURL(),
+6 -2
View File
@@ -44,12 +44,16 @@ func (api *API) appearance(rw http.ResponseWriter, r *http.Request) {
type appearanceFetcher struct {
database database.Store
supportLinks []codersdk.LinkConfig
docsURL string
coderVersion string
}
func newAppearanceFetcher(store database.Store, links []codersdk.LinkConfig) agpl.Fetcher {
func newAppearanceFetcher(store database.Store, links []codersdk.LinkConfig, docsURL, coderVersion string) agpl.Fetcher {
return &appearanceFetcher{
database: store,
supportLinks: links,
docsURL: docsURL,
coderVersion: coderVersion,
}
}
@@ -90,7 +94,7 @@ func (f *appearanceFetcher) Fetch(ctx context.Context) (codersdk.AppearanceConfi
ApplicationName: applicationName,
LogoURL: logoURL,
AnnouncementBanners: []codersdk.BannerConfig{},
SupportLinks: agpl.DefaultSupportLinks,
SupportLinks: agpl.DefaultSupportLinks(f.docsURL),
}
if announcementBannersJSON != "" {
+22 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"net/http"
"net/url"
"testing"
"github.com/stretchr/testify/require"
@@ -229,6 +230,26 @@ func TestCustomSupportLinks(t *testing.T) {
require.Equal(t, supportLinks, appr.SupportLinks)
}
func TestDefaultSupportLinksWithCustomDocsUrl(t *testing.T) {
t.Parallel()
// Don't need to set the license, as default links are passed without it.
testURLRawString := "http://google.com"
testURL, err := url.Parse(testURLRawString)
require.NoError(t, err)
cfg := coderdtest.DeploymentValues(t)
cfg.DocsURL = *serpent.URLOf(testURL)
adminClient, adminUser := coderdenttest.New(t, &coderdenttest.Options{DontAddLicense: true, Options: &coderdtest.Options{DeploymentValues: cfg}})
anotherClient, _ := coderdtest.CreateAnotherUser(t, adminClient, adminUser.OrganizationID)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
defer cancel()
appr, err := anotherClient.Appearance(ctx)
require.NoError(t, err)
require.Equal(t, appearance.DefaultSupportLinks(testURLRawString), appr.SupportLinks)
}
func TestDefaultSupportLinks(t *testing.T) {
t.Parallel()
@@ -241,5 +262,5 @@ func TestDefaultSupportLinks(t *testing.T) {
appr, err := anotherClient.Appearance(ctx)
require.NoError(t, err)
require.Equal(t, appearance.DefaultSupportLinks, appr.SupportLinks)
require.Equal(t, appearance.DefaultSupportLinks(""), appr.SupportLinks)
}
+5 -1
View File
@@ -12,6 +12,7 @@ import (
"sync"
"time"
"github.com/coder/coder/v2/buildinfo"
"github.com/coder/coder/v2/coderd/appearance"
"github.com/coder/coder/v2/coderd/database"
agplportsharing "github.com/coder/coder/v2/coderd/portsharing"
@@ -791,10 +792,13 @@ func (api *API) updateEntitlements(ctx context.Context) error {
f := newAppearanceFetcher(
api.Database,
api.DeploymentValues.Support.Links.Value,
api.DeploymentValues.DocsURL.String(),
buildinfo.Version(),
)
api.AGPL.AppearanceFetcher.Store(&f)
} else {
api.AGPL.AppearanceFetcher.Store(&appearance.DefaultFetcher)
f := appearance.NewDefaultFetcher(api.DeploymentValues.DocsURL.String())
api.AGPL.AppearanceFetcher.Store(&f)
}
}
+2 -1
View File
@@ -84,7 +84,8 @@ type Options struct {
func New(opts *Options) *Handler {
if opts.AppearanceFetcher == nil {
daf := atomic.Pointer[appearance.Fetcher]{}
daf.Store(&appearance.DefaultFetcher)
f := appearance.NewDefaultFetcher(opts.DocsURL)
daf.Store(&f)
opts.AppearanceFetcher = &daf
}
handler := &Handler{
@@ -93,7 +93,7 @@ export const UserDropdownContent: FC<UserDropdownContentProps> = ({
<Divider />
{supportLinks.map((link) => (
<a
href={includeBuildInfo(link.target, buildInfo)}
href={link.target}
key={link.name}
target="_blank"
rel="noreferrer"
@@ -177,18 +177,6 @@ export const GithubStar: FC<SvgIconProps> = (props) => (
</svg>
);
const includeBuildInfo = (
href: string,
buildInfo?: TypesGen.BuildInfoResponse,
): string => {
return href.replace(
"{CODER_BUILD_INFO}",
`${encodeURIComponent(
`Version: [\`${buildInfo?.version}\`](${buildInfo?.external_url})`,
)}`,
);
};
const styles = {
info: (theme) => [
theme.typography.body2 as CSSObject,