[pkgsite] cmd/internal/pkgsite: show available modules at / in godoc mode

0 views
Skip to first unread message

Filippo Valsorda (Gerrit)

unread,
2:07 PM (5 hours ago) 2:07 PM
to goph...@pubsubhelper.golang.org, Filippo Valsorda, golang-co...@googlegroups.com

Filippo Valsorda has uploaded the change for review

Commit message

cmd/internal/pkgsite: show available modules at / in godoc mode

Previously the homepage just showed a search box and a link to the
main module. Dependencies were browsable, but not discoverable.
Change-Id: I3a83800a6a5160f4a1f1d75b50028b816a6a6964

Change diff

diff --git a/cmd/internal/pkgsite/server.go b/cmd/internal/pkgsite/server.go
index 32986a5..7e7c6a0 100644
--- a/cmd/internal/pkgsite/server.go
+++ b/cmd/internal/pkgsite/server.go
@@ -10,10 +10,12 @@
"encoding/json"
"fmt"
"io/fs"
+ "maps"
"net/http"
"os"
"os/exec"
"path/filepath"
+ "slices"
"sort"
"strings"
"time"
@@ -101,21 +103,30 @@

// Collect unique module Paths served by this server.
seenModules := make(map[frontend.LocalModule]bool)
- var allModules []frontend.LocalModule
+ var localModules []frontend.LocalModule
for _, modules := range cfg.dirs {
for _, m := range modules {
if seenModules[m] {
continue
}
seenModules[m] = true
- allModules = append(allModules, m)
+ localModules = append(localModules, m)
}
}
- sort.Slice(allModules, func(i, j int) bool {
- return allModules[i].ModulePath < allModules[j].ModulePath
+ sort.Slice(localModules, func(i, j int) bool {
+ return localModules[i].ModulePath < localModules[j].ModulePath
})

- return newServer(getters, allModules, cfg.proxy, serverCfg.GoDocMode, serverCfg.DevMode, serverCfg.DevModeStaticDir)
+ // Collect dependencies.
+ var directDeps, indirectDeps []frontend.LocalModule
+ if !serverCfg.GOPATHMode && serverCfg.UseListedMods {
+ directDeps, indirectDeps, err = getModuleDependencies(serverCfg.Paths, localModules)
+ if err != nil {
+ return nil, fmt.Errorf("getting module dependencies: %v", err)
+ }
+ }
+
+ return newServer(getters, localModules, directDeps, indirectDeps, cfg.proxy, serverCfg.GoDocMode, serverCfg.DevMode, serverCfg.DevModeStaticDir)
}

// getModuleDirs returns the set of workspace modules for each directory,
@@ -157,6 +168,62 @@
return dirModules, nil
}

+// getModuleDependencies returns all dependencies for the given directory,
+// determined by running "go list -m -json all".
+//
+// It returns two slices: direct dependencies (Indirect=false) and indirect
+// dependencies (Indirect=true). Modules without a Dir field (unreachable
+// modules) are filtered out. The main module itself is also excluded.
+func getModuleDependencies(dirs []string, localModules []frontend.LocalModule) (direct, indirect []frontend.LocalModule, err error) {
+ directMods, indirectMods := make(map[frontend.LocalModule]bool), make(map[frontend.LocalModule]bool)
+ mainModulePaths := make(map[string]bool)
+ for _, lm := range localModules {
+ mainModulePaths[lm.ModulePath] = true
+ }
+ for _, dir := range dirs {
+ output, err := runGo(dir, "list", "-m", "-json", "all")
+ if err != nil {
+ return nil, nil, fmt.Errorf("listing all modules in %s: %v", dir, err)
+ }
+ decoder := json.NewDecoder(bytes.NewBuffer(output))
+ for decoder.More() {
+ var m struct {
+ ModulePath string `json:"Path"`
+ Dir string `json:"Dir"`
+ Indirect bool `json:"Indirect"`
+ }
+ if err := decoder.Decode(&m); err != nil {
+ return nil, nil, err
+ }
+ // Skip modules without a Dir (not downloaded/unreachable)
+ if m.Dir == "" {
+ continue
+ }
+ // Skip the main module(s) themselves and special modules
+ if mainModulePaths[m.ModulePath] {
+ continue
+ }
+ if m.ModulePath == "std" || m.ModulePath == "command-line-arguments" {
+ continue
+ }
+ if m.Indirect {
+ mm := frontend.LocalModule{ModulePath: m.ModulePath, Dir: m.Dir}
+ indirectMods[mm] = true
+ } else {
+ mm := frontend.LocalModule{ModulePath: m.ModulePath, Dir: m.Dir}
+ directMods[mm] = true
+ }
+ }
+ }
+ direct = slices.SortedFunc(maps.Keys(directMods), func(a, b frontend.LocalModule) int {
+ return strings.Compare(a.ModulePath, b.ModulePath)
+ })
+ indirect = slices.SortedFunc(maps.Keys(indirectMods), func(a, b frontend.LocalModule) int {
+ return strings.Compare(a.ModulePath, b.ModulePath)
+ })
+ return direct, indirect, nil
+}
+
// getGOPATHModuleDirs returns local module information for directories in
// GOPATH corresponding to the requested module Paths.
//
@@ -276,7 +343,7 @@
return getters, nil
}

-func newServer(getters []fetch.ModuleGetter, localModules []frontend.LocalModule, prox *proxy.Client, goDocMode bool, devMode bool, staticFlag string) (*frontend.Server, error) {
+func newServer(getters []fetch.ModuleGetter, localModules, directDeps, indirectDeps []frontend.LocalModule, prox *proxy.Client, goDocMode bool, devMode bool, staticFlag string) (*frontend.Server, error) {
lds := fetchdatasource.Options{
Getters: getters,
ProxyClientForLatest: prox,
@@ -299,14 +366,16 @@
go lds.GetUnitMeta(context.Background(), "", "std", "latest")

server, err := frontend.NewServer(frontend.ServerConfig{
- DataSourceGetter: func(context.Context) internal.DataSource { return lds },
- TemplateFS: template.TrustedFSFromEmbed(static.FS),
- StaticFS: staticFS,
- DevMode: devMode,
- GoDocMode: goDocMode,
- LocalMode: true,
- LocalModules: localModules,
- ThirdPartyFS: thirdparty.FS,
+ DataSourceGetter: func(context.Context) internal.DataSource { return lds },
+ TemplateFS: template.TrustedFSFromEmbed(static.FS),
+ StaticFS: staticFS,
+ DevMode: devMode,
+ GoDocMode: goDocMode,
+ LocalMode: true,
+ LocalModules: localModules,
+ DirectDependencies: directDeps,
+ IndirectDependencies: indirectDeps,
+ ThirdPartyFS: thirdparty.FS,
})
if err != nil {
return nil, err
diff --git a/cmd/internal/pkgsite/server_test.go b/cmd/internal/pkgsite/server_test.go
index 49d0921..59ae9e4 100644
--- a/cmd/internal/pkgsite/server_test.go
+++ b/cmd/internal/pkgsite/server_test.go
@@ -51,6 +51,28 @@
-- a.go --
package a
`)
+
+ // Create a module with a dependency for testing the homepage dependencies section.
+ // Both modules are in subdirectories so we can use a relative replace directive.
+ localModuleWithDep, _ := testhelper.WriteTxtarToTempDir(t, `
+-- main/go.mod --
+module example.com/withdep
+
+require example.com/dep v0.0.0
+
+replace example.com/dep => ../dep
+-- main/main.go --
+package main
+
+import _ "example.com/dep"
+-- dep/go.mod --
+module example.com/dep
+-- dep/dep.go --
+package dep
+
+var X = 1
+`)
+ localModuleWithDep = filepath.Join(localModuleWithDep, "main")
cacheDir := repoPath("internal/fetch/testdata/modcache")
testModules := proxytest.LoadTestModules(repoPath("internal/proxy/testdata"))
prox, teardown := proxytest.SetupTestClient(t, testModules)
@@ -190,6 +212,30 @@
http.StatusFailedDependency,
hasText("page is not supported"),
},
+ {
+ "homepage local modules",
+ cfg(func(c *ServerConfig) {
+ c.UseLocalStdlib = false
+ }),
+ "",
+ http.StatusOK,
+ in("",
+ in(".Homepage-mainModule", hasText("example.com/testmod")),
+ in(".Homepage-stdlib a", hasText("Browse Standard Library"))),
+ },
+ {
+ "homepage with dependencies",
+ cfg(func(c *ServerConfig) {
+ c.Paths = []string{localModuleWithDep}
+ c.UseLocalStdlib = false
+ }),
+ "",
+ http.StatusOK,
+ in("",
+ in(".Homepage-mainModule", hasText("example.com/withdep")),
+ in(".Homepage-dependencies", hasText("example.com/dep")),
+ in(".Homepage-stdlib a", hasText("Browse Standard Library"))),
+ },
// TODO(rfindley): add a test for the standard library once it doesn't go
// through the stdlib package.
// See also golang/go#58923.
diff --git a/internal/frontend/homepage.go b/internal/frontend/homepage.go
index 1ec5a72..15de91b 100644
--- a/internal/frontend/homepage.go
+++ b/internal/frontend/homepage.go
@@ -51,6 +51,14 @@
// LocalModules holds locally-hosted modules, for quick navigation.
// Empty in production.
LocalModules []LocalModule
+
+ // DirectDependencies holds direct dependencies of the local module(s).
+ // Empty in production.
+ DirectDependencies []LocalModule
+
+ // IndirectDependencies holds indirect (transitive) dependencies.
+ // Empty in production.
+ IndirectDependencies []LocalModule
}

// LocalModule holds information about a locally-hosted module.
@@ -63,9 +71,11 @@

func (s *Server) serveHomepage(ctx context.Context, w http.ResponseWriter, r *http.Request) {
s.servePage(ctx, w, "homepage", Homepage{
- BasePage: s.newBasePage(r, "Go Packages"),
- SearchTips: searchTips,
- TipIndex: rand.Intn(len(searchTips)),
- LocalModules: s.localModules,
+ BasePage: s.newBasePage(r, "Go Packages"),
+ SearchTips: searchTips,
+ TipIndex: rand.Intn(len(searchTips)),
+ LocalModules: s.localModules,
+ DirectDependencies: s.directDependencies,
+ IndirectDependencies: s.indirectDependencies,
})
}
diff --git a/internal/frontend/server.go b/internal/frontend/server.go
index 9648c5e..97b6ad9 100644
--- a/internal/frontend/server.go
+++ b/internal/frontend/server.go
@@ -51,6 +51,8 @@
goDocMode bool // running to serve documentation for 'go doc'
localMode bool // running locally (i.e. ./cmd/pkgsite)
localModules []LocalModule // locally hosted modules; empty in production
+ directDependencies []LocalModule // direct dependencies; empty in production
+ indirectDependencies []LocalModule // indirect dependencies; empty in production
errorPage []byte
appVersionLabel string
googleTagManagerID string
@@ -96,6 +98,8 @@
LocalMode bool
GoDocMode bool
LocalModules []LocalModule
+ DirectDependencies []LocalModule
+ IndirectDependencies []LocalModule
Reporter derrors.Reporter
VulndbClient *vuln.Client
HTTPClient *http.Client
@@ -121,6 +125,8 @@
localMode: scfg.LocalMode,
goDocMode: scfg.GoDocMode,
localModules: scfg.LocalModules,
+ directDependencies: scfg.DirectDependencies,
+ indirectDependencies: scfg.IndirectDependencies,
templates: ts,
reporter: scfg.Reporter,
fileMux: http.NewServeMux(),
diff --git a/static/frontend/homepage/homepage.css b/static/frontend/homepage/homepage.css
index 5961756..ab41c62 100644
--- a/static/frontend/homepage/homepage.css
+++ b/static/frontend/homepage/homepage.css
@@ -150,25 +150,88 @@
width: 1rem;
}

-.Homepage-modules {
- margin: auto;
- max-width: 45.0625rem;
- width: 100%;
+/* Local mode homepage styles */
+.Homepage-local {
+ max-width: 60rem;
+ margin: 0 auto;
+ padding: 1.5rem;
}

-.Homepage-modules-header {
- color: var(--color-text);
- font-weight: bold;
+.Homepage-search--local {
+ margin: 1rem auto 2rem;
}

-.Homepage-modules ul {
- list-style: circle;
- padding: 0 1.5rem;
+.Homepage-localSection {
+ margin-bottom: 2rem;
}

-.Homepage-modules ul > li {
- font-size: 1rem;
- line-height: 1.75rem;
+.Homepage-localSection h2 {
+ font-size: 1.125rem;
+ margin: 0 0 0.75rem;
+ padding-bottom: 0.5rem;
+ border-bottom: var(--border);
+}
+
+.Homepage-localSection ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.Homepage-localSection li {
+ padding: 0.25rem 0;
+}
+
+.Homepage-mainModule ul {
+ background: var(--color-background-accented);
+ border-radius: var(--border-radius);
+ padding: 1rem;
+}
+
+.Homepage-mainModule li {
+ padding: 0.5rem 0;
+}
+
+.Homepage-mainModule a {
+ font-size: 1.125rem;
+ font-weight: 500;
+}
+
+.Homepage-mainModule small {
+ color: var(--color-text-subtle);
+ display: block;
+ font-size: 0.8125rem;
+ margin-top: 0.25rem;
+}
+
+.Homepage-mainModule {
+ margin-bottom: 2.5rem;
+}
+
+.Homepage-dependencies {
+ margin-bottom: 0.5rem;
+}
+
+.Homepage-transitive {
+ margin: 0;
+}
+
+.Homepage-transitive summary {
+ cursor: pointer;
+ color: var(--color-text-subtle);
+ font-size: 0.9375rem;
+ padding-left: 0.25rem;
+}
+
+.Homepage-transitive[open] summary {
+ margin-bottom: 0.25rem;
+}
+
+.Homepage-stdlib {
+ text-align: center;
+ margin: 1rem 0 0;
+ padding-top: 0.75rem;
+ border-top: var(--border);
}

.Questions {
diff --git a/static/frontend/homepage/homepage.min.css b/static/frontend/homepage/homepage.min.css
index 755b4df..7a96a02 100644
--- a/static/frontend/homepage/homepage.min.css
+++ b/static/frontend/homepage/homepage.min.css
@@ -3,7 +3,7 @@
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
-.go-SearchForm{display:none}.Homepage-logo{border-radius:var(--border-radius);display:block;height:10rem;margin:3.125rem auto;width:auto}[data-theme=dark] .Homepage-logo{mix-blend-mode:difference}@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .Homepage-logo{mix-blend-mode:difference}}@media only screen and (min-width: 52rem){.Homepage{margin:2rem auto}.Homepage-logo{margin:3.5rem auto}}.Homepage-search{--border-radius: .5rem;height:3rem;margin:2.5rem auto 0;max-width:45.0625rem;position:relative;width:100%}.Homepage-search:before{background:url(/static/shared/icon/search_gm_grey_24dp.svg) left no-repeat;content:"";height:3rem;left:.75rem;position:absolute;width:1.5rem;z-index:3}.Homepage-search .go-Select,.Homepage-search .go-Input{padding-left:2.5rem}.Homepage-search--symbol .go-Input{border-bottom-right-radius:var(--border-radius);border-top-right-radius:var(--border-radius);padding-left:2.5rem}.Homepage-search .go-Button{justify-content:center;width:7.375rem}.Homepage-search--symbol .go-Button{display:none}@media only screen and (min-width: 30rem){.Homepage-search--symbol .go-Input{border-bottom-right-radius:0;border-top-right-radius:0}.Homepage-search--symbol .go-Button{display:inline-flex}}input[type=search]::-webkit-search-decoration{display:none}.Homepage-tips{margin:auto;max-width:45.0625rem;width:100%}[data-local=true] .Homepage-tips{display:none}.Homepage-examples{align-items:center;display:flex;flex-direction:column;font-size:.875rem;gap:.5rem 1rem;justify-content:space-between;margin:0 auto;max-width:45.0625rem;white-space:nowrap;width:inherit}@media only screen and (min-width: 52rem){.Homepage-examples{flex-direction:row}}.Homepage-examplesTitle{color:var(--color-text-subtle);font-weight:500;text-transform:uppercase}.Homepage-examplesList{display:flex;flex-grow:1;flex-wrap:wrap;gap:.5rem 2rem}a.Homepage-helpLink{align-items:center;display:inline-flex;font-size:1em;font-weight:initial;margin-left:.5rem;white-space:nowrap}.Homepage-helpLink img{height:1rem;margin-left:.25rem;position:relative;top:.1875rem;width:1rem}.Homepage-modules{margin:auto;max-width:45.0625rem;width:100%}.Homepage-modules-header{color:var(--color-text);font-weight:700}.Homepage-modules ul{list-style:circle;padding:0 1.5rem}.Homepage-modules ul>li{font-size:1rem;line-height:1.75rem}.Questions{background:var(--color-background-accented);color:var(--color-text);display:flex;padding-bottom:1rem;padding-top:.5rem}.Questions-header{color:var(--color-text);font-weight:700;margin:1rem 0}.Questions-content{flex-grow:1;margin:0 auto;max-width:75.75rem;padding:0 1.5rem}.Questions-content a{color:var(--color-bright-text-link)}.Questions-content ul{list-style:none;padding-inline-start:0}.Questions-content ul>li{font-size:.875rem;line-height:1.75rem}
+.go-SearchForm{display:none}.Homepage-logo{border-radius:var(--border-radius);display:block;height:10rem;margin:3.125rem auto;width:auto}[data-theme=dark] .Homepage-logo{mix-blend-mode:difference}@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .Homepage-logo{mix-blend-mode:difference}}@media only screen and (min-width: 52rem){.Homepage{margin:2rem auto}.Homepage-logo{margin:3.5rem auto}}.Homepage-search{--border-radius: .5rem;height:3rem;margin:2.5rem auto 0;max-width:45.0625rem;position:relative;width:100%}.Homepage-search:before{background:url(/static/shared/icon/search_gm_grey_24dp.svg) left no-repeat;content:"";height:3rem;left:.75rem;position:absolute;width:1.5rem;z-index:3}.Homepage-search .go-Select,.Homepage-search .go-Input{padding-left:2.5rem}.Homepage-search--symbol .go-Input{border-bottom-right-radius:var(--border-radius);border-top-right-radius:var(--border-radius);padding-left:2.5rem}.Homepage-search .go-Button{justify-content:center;width:7.375rem}.Homepage-search--symbol .go-Button{display:none}@media only screen and (min-width: 30rem){.Homepage-search--symbol .go-Input{border-bottom-right-radius:0;border-top-right-radius:0}.Homepage-search--symbol .go-Button{display:inline-flex}}input[type=search]::-webkit-search-decoration{display:none}.Homepage-tips{margin:auto;max-width:45.0625rem;width:100%}[data-local=true] .Homepage-tips{display:none}.Homepage-examples{align-items:center;display:flex;flex-direction:column;font-size:.875rem;gap:.5rem 1rem;justify-content:space-between;margin:0 auto;max-width:45.0625rem;white-space:nowrap;width:inherit}@media only screen and (min-width: 52rem){.Homepage-examples{flex-direction:row}}.Homepage-examplesTitle{color:var(--color-text-subtle);font-weight:500;text-transform:uppercase}.Homepage-examplesList{display:flex;flex-grow:1;flex-wrap:wrap;gap:.5rem 2rem}a.Homepage-helpLink{align-items:center;display:inline-flex;font-size:1em;font-weight:initial;margin-left:.5rem;white-space:nowrap}.Homepage-helpLink img{height:1rem;margin-left:.25rem;position:relative;top:.1875rem;width:1rem}.Homepage-local{max-width:60rem;margin:0 auto;padding:1.5rem}.Homepage-search--local{margin:1rem auto 2rem}.Homepage-localSection{margin-bottom:2rem}.Homepage-localSection h2{font-size:1.125rem;margin:0 0 .75rem;padding-bottom:.5rem;border-bottom:var(--border)}.Homepage-localSection ul{list-style:none;margin:0;padding:0}.Homepage-localSection li{padding:.25rem 0}.Homepage-mainModule ul{background:var(--color-background-accented);border-radius:var(--border-radius);padding:1rem}.Homepage-mainModule li{padding:.5rem 0}.Homepage-mainModule a{font-size:1.125rem;font-weight:500}.Homepage-mainModule small{color:var(--color-text-subtle);display:block;font-size:.8125rem;margin-top:.25rem}.Homepage-mainModule{margin-bottom:2.5rem}.Homepage-dependencies{margin-bottom:.5rem}.Homepage-transitive{margin:0}.Homepage-transitive summary{cursor:pointer;color:var(--color-text-subtle);font-size:.9375rem;padding-left:.25rem}.Homepage-transitive[open] summary{margin-bottom:.25rem}.Homepage-stdlib{text-align:center;margin:1rem 0 0;padding-top:.75rem;border-top:var(--border)}.Questions{background:var(--color-background-accented);color:var(--color-text);display:flex;padding-bottom:1rem;padding-top:.5rem}.Questions-header{color:var(--color-text);font-weight:700;margin:1rem 0}.Questions-content{flex-grow:1;margin:0 auto;max-width:75.75rem;padding:0 1.5rem}.Questions-content a{color:var(--color-bright-text-link)}.Questions-content ul{list-style:none;padding-inline-start:0}.Questions-content ul>li{font-size:.875rem;line-height:1.75rem}
/*!
* Copyright 2020 The Go Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
diff --git a/static/frontend/homepage/homepage.min.css.map b/static/frontend/homepage/homepage.min.css.map
index 031143e..5fb6209 100644
--- a/static/frontend/homepage/homepage.min.css.map
+++ b/static/frontend/homepage/homepage.min.css.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["homepage.css"],
- "sourcesContent": ["/*!\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/* Hide the search form in the header. */\n.go-SearchForm {\n display: none;\n}\n\n.Homepage-logo {\n border-radius: var(--border-radius);\n display: block;\n height: 10rem;\n margin: 3.125rem auto;\n width: auto;\n}\n\n[data-theme='dark'] .Homepage-logo {\n mix-blend-mode: difference;\n}\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme='light']) .Homepage-logo {\n mix-blend-mode: difference;\n }\n}\n@media only screen and (min-width: 52rem) {\n .Homepage {\n margin: 2rem auto;\n }\n\n .Homepage-logo {\n margin: 3.5rem auto;\n }\n}\n\n.Homepage-search {\n --border-radius: 0.5rem;\n\n height: 3rem;\n margin: 2.5rem auto 0;\n max-width: 45.0625rem;\n position: relative;\n width: 100%;\n}\n\n.Homepage-search::before {\n background: url('/static/shared/icon/search_gm_grey_24dp.svg') left no-repeat;\n content: '';\n height: 3rem;\n left: 0.75rem;\n position: absolute;\n width: 1.5rem;\n z-index: 3;\n}\n\n.Homepage-search .go-Select {\n padding-left: 2.5rem;\n}\n\n.Homepage-search .go-Input {\n padding-left: 2.5rem;\n}\n\n.Homepage-search--symbol .go-Input {\n border-bottom-right-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n padding-left: 2.5rem;\n}\n\n.Homepage-search .go-Button {\n justify-content: center;\n width: 7.375rem;\n}\n\n.Homepage-search--symbol .go-Button {\n display: none;\n}\n@media only screen and (min-width: 30rem) {\n .Homepage-search--symbol .go-Input {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n }\n\n .Homepage-search--symbol .go-Button {\n display: inline-flex;\n }\n}\n\ninput[type='search']::-webkit-search-decoration {\n display: none;\n}\n\n.Homepage-tips {\n margin: auto;\n max-width: 45.0625rem;\n width: 100%;\n}\n\n[data-local='true'] .Homepage-tips {\n display: none;\n}\n\n.Homepage-examples {\n align-items: center;\n display: flex;\n flex-direction: column;\n font-size: 0.875rem;\n gap: 0.5rem 1rem;\n justify-content: space-between;\n margin: 0 auto;\n max-width: 45.0625rem;\n white-space: nowrap;\n width: inherit;\n}\n@media only screen and (min-width: 52rem) {\n .Homepage-examples {\n flex-direction: row;\n }\n}\n\n.Homepage-examplesTitle {\n color: var(--color-text-subtle);\n font-weight: 500;\n text-transform: uppercase;\n}\n\n.Homepage-examplesList {\n display: flex;\n flex-grow: 1;\n flex-wrap: wrap;\n gap: 0.5rem 2rem;\n}\n\na.Homepage-helpLink {\n align-items: center;\n display: inline-flex;\n font-size: 1em;\n font-weight: initial;\n margin-left: 0.5rem;\n white-space: nowrap;\n}\n\n.Homepage-helpLink img {\n height: 1rem;\n margin-left: 0.25rem;\n position: relative;\n top: 0.1875rem;\n width: 1rem;\n}\n\n.Homepage-modules {\n margin: auto;\n max-width: 45.0625rem;\n width: 100%;\n}\n\n.Homepage-modules-header {\n color: var(--color-text);\n font-weight: bold;\n}\n\n.Homepage-modules ul {\n list-style: circle;\n padding: 0 1.5rem;\n}\n\n.Homepage-modules ul > li {\n font-size: 1rem;\n line-height: 1.75rem;\n}\n\n.Questions {\n background: var(--color-background-accented);\n color: var(--color-text);\n display: flex;\n padding-bottom: 1rem;\n padding-top: 0.5rem;\n}\n\n.Questions-header {\n color: var(--color-text);\n font-weight: bold;\n margin: 1rem 0;\n}\n\n.Questions-content {\n flex-grow: 1;\n margin: 0 auto;\n max-width: 75.75rem;\n padding: 0 1.5rem;\n}\n\n.Questions-content a {\n color: var(--color-bright-text-link);\n}\n\n.Questions-content ul {\n list-style: none;\n padding-inline-start: 0;\n}\n\n.Questions-content ul > li {\n font-size: 0.875rem;\n line-height: 1.75rem;\n}\n"],
- "mappings": ";;;;;AAOA,eACE,aAGF,eACE,mCACA,cACA,aAdF,qBAgBE,WAGF,iCACE,0BAEF,oCACE,+CACE,2BAGJ,0CACE,UA5BF,iBAgCE,eAhCF,oBAqCA,iBACE,uBAEA,YAxCF,qBA0CE,qBACA,kBACA,WAGF,wBACE,2EACA,WACA,YACA,YACA,kBACA,aACA,UAGF,uDACE,oBAOF,mCACE,gDACA,6CACA,oBAGF,4BACE,uBACA,eAGF,oCACE,aAEF,0CACE,mCACE,6BACA,0BAGF,oCACE,qBAIJ,8CACE,aAGF,eA9FA,YAgGE,qBACA,WAGF,iCACE,aAGF,mBACE,mBACA,aACA,sBACA,kBACA,eACA,8BA9GF,cAgHE,qBACA,mBACA,cAEF,0CACE,mBACE,oBAIJ,wBACE,+BACA,gBACA,yBAGF,uBACE,aACA,YACA,eACA,eAGF,oBACE,mBACA,oBACA,cACA,oBACA,kBACA,mBAGF,uBACE,YACA,mBACA,kBACA,aACA,WAGF,kBAxJA,YA0JE,qBACA,WAGF,yBACE,wBACA,gBAGF,qBACE,kBApKF,iBAwKA,wBACE,eACA,oBAGF,WACE,4CACA,wBACA,aACA,oBACA,kBAGF,kBACE,wBACA,gBAvLF,cA2LA,mBACE,YA5LF,cA8LE,mBA9LF,iBAkMA,qBACE,oCAGF,sBACE,gBACA,uBAGF,yBACE,kBACA",
+ "sourcesContent": ["/*!\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/* Hide the search form in the header. */\n.go-SearchForm {\n display: none;\n}\n\n.Homepage-logo {\n border-radius: var(--border-radius);\n display: block;\n height: 10rem;\n margin: 3.125rem auto;\n width: auto;\n}\n\n[data-theme='dark'] .Homepage-logo {\n mix-blend-mode: difference;\n}\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme='light']) .Homepage-logo {\n mix-blend-mode: difference;\n }\n}\n@media only screen and (min-width: 52rem) {\n .Homepage {\n margin: 2rem auto;\n }\n\n .Homepage-logo {\n margin: 3.5rem auto;\n }\n}\n\n.Homepage-search {\n --border-radius: 0.5rem;\n\n height: 3rem;\n margin: 2.5rem auto 0;\n max-width: 45.0625rem;\n position: relative;\n width: 100%;\n}\n\n.Homepage-search::before {\n background: url('/static/shared/icon/search_gm_grey_24dp.svg') left no-repeat;\n content: '';\n height: 3rem;\n left: 0.75rem;\n position: absolute;\n width: 1.5rem;\n z-index: 3;\n}\n\n.Homepage-search .go-Select {\n padding-left: 2.5rem;\n}\n\n.Homepage-search .go-Input {\n padding-left: 2.5rem;\n}\n\n.Homepage-search--symbol .go-Input {\n border-bottom-right-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n padding-left: 2.5rem;\n}\n\n.Homepage-search .go-Button {\n justify-content: center;\n width: 7.375rem;\n}\n\n.Homepage-search--symbol .go-Button {\n display: none;\n}\n@media only screen and (min-width: 30rem) {\n .Homepage-search--symbol .go-Input {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n }\n\n .Homepage-search--symbol .go-Button {\n display: inline-flex;\n }\n}\n\ninput[type='search']::-webkit-search-decoration {\n display: none;\n}\n\n.Homepage-tips {\n margin: auto;\n max-width: 45.0625rem;\n width: 100%;\n}\n\n[data-local='true'] .Homepage-tips {\n display: none;\n}\n\n.Homepage-examples {\n align-items: center;\n display: flex;\n flex-direction: column;\n font-size: 0.875rem;\n gap: 0.5rem 1rem;\n justify-content: space-between;\n margin: 0 auto;\n max-width: 45.0625rem;\n white-space: nowrap;\n width: inherit;\n}\n@media only screen and (min-width: 52rem) {\n .Homepage-examples {\n flex-direction: row;\n }\n}\n\n.Homepage-examplesTitle {\n color: var(--color-text-subtle);\n font-weight: 500;\n text-transform: uppercase;\n}\n\n.Homepage-examplesList {\n display: flex;\n flex-grow: 1;\n flex-wrap: wrap;\n gap: 0.5rem 2rem;\n}\n\na.Homepage-helpLink {\n align-items: center;\n display: inline-flex;\n font-size: 1em;\n font-weight: initial;\n margin-left: 0.5rem;\n white-space: nowrap;\n}\n\n.Homepage-helpLink img {\n height: 1rem;\n margin-left: 0.25rem;\n position: relative;\n top: 0.1875rem;\n width: 1rem;\n}\n\n/* Local mode homepage styles */\n.Homepage-local {\n max-width: 60rem;\n margin: 0 auto;\n padding: 1.5rem;\n}\n\n.Homepage-search--local {\n margin: 1rem auto 2rem;\n}\n\n.Homepage-localSection {\n margin-bottom: 2rem;\n}\n\n.Homepage-localSection h2 {\n font-size: 1.125rem;\n margin: 0 0 0.75rem;\n padding-bottom: 0.5rem;\n border-bottom: var(--border);\n}\n\n.Homepage-localSection ul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.Homepage-localSection li {\n padding: 0.25rem 0;\n}\n\n.Homepage-mainModule ul {\n background: var(--color-background-accented);\n border-radius: var(--border-radius);\n padding: 1rem;\n}\n\n.Homepage-mainModule li {\n padding: 0.5rem 0;\n}\n\n.Homepage-mainModule a {\n font-size: 1.125rem;\n font-weight: 500;\n}\n\n.Homepage-mainModule small {\n color: var(--color-text-subtle);\n display: block;\n font-size: 0.8125rem;\n margin-top: 0.25rem;\n}\n\n.Homepage-mainModule {\n margin-bottom: 2.5rem;\n}\n\n.Homepage-dependencies {\n margin-bottom: 0.5rem;\n}\n\n.Homepage-transitive {\n margin: 0;\n}\n\n.Homepage-transitive summary {\n cursor: pointer;\n color: var(--color-text-subtle);\n font-size: 0.9375rem;\n padding-left: 0.25rem;\n}\n\n.Homepage-transitive[open] summary {\n margin-bottom: 0.25rem;\n}\n\n.Homepage-stdlib {\n text-align: center;\n margin: 1rem 0 0;\n padding-top: 0.75rem;\n border-top: var(--border);\n}\n\n.Questions {\n background: var(--color-background-accented);\n color: var(--color-text);\n display: flex;\n padding-bottom: 1rem;\n padding-top: 0.5rem;\n}\n\n.Questions-header {\n color: var(--color-text);\n font-weight: bold;\n margin: 1rem 0;\n}\n\n.Questions-content {\n flex-grow: 1;\n margin: 0 auto;\n max-width: 75.75rem;\n padding: 0 1.5rem;\n}\n\n.Questions-content a {\n color: var(--color-bright-text-link);\n}\n\n.Questions-content ul {\n list-style: none;\n padding-inline-start: 0;\n}\n\n.Questions-content ul > li {\n font-size: 0.875rem;\n line-height: 1.75rem;\n}\n"],
+ "mappings": ";;;;;AAOA,eACE,aAGF,eACE,mCACA,cACA,aAdF,qBAgBE,WAGF,iCACE,0BAEF,oCACE,+CACE,2BAGJ,0CACE,UA5BF,iBAgCE,eAhCF,oBAqCA,iBACE,uBAEA,YAxCF,qBA0CE,qBACA,kBACA,WAGF,wBACE,2EACA,WACA,YACA,YACA,kBACA,aACA,UAGF,uDACE,oBAOF,mCACE,gDACA,6CACA,oBAGF,4BACE,uBACA,eAGF,oCACE,aAEF,0CACE,mCACE,6BACA,0BAGF,oCACE,qBAIJ,8CACE,aAGF,eA9FA,YAgGE,qBACA,WAGF,iCACE,aAGF,mBACE,mBACA,aACA,sBACA,kBACA,eACA,8BA9GF,cAgHE,qBACA,mBACA,cAEF,0CACE,mBACE,oBAIJ,wBACE,+BACA,gBACA,yBAGF,uBACE,aACA,YACA,eACA,eAGF,oBACE,mBACA,oBACA,cACA,oBACA,kBACA,mBAGF,uBACE,YACA,mBACA,kBACA,aACA,WAIF,gBACE,gBA1JF,6BA+JA,wBA/JA,sBAmKA,uBACE,mBAGF,0BACE,mBAxKF,kBA0KE,qBACA,4BAGF,0BACE,gBA/KF,mBAoLA,0BApLA,iBAwLA,wBACE,4CACA,mCA1LF,aA8LA,wBA9LA,gBAkMA,uBACE,mBACA,gBAGF,2BACE,+BACA,cACA,mBACA,kBAGF,qBACE,qBAGF,uBACE,oBAGF,qBAtNA,SA0NA,6BACE,eACA,+BACA,mBACA,oBAGF,mCACE,qBAGF,iBACE,kBAtOF,gBAwOE,mBACA,yBAGF,WACE,4CACA,wBACA,aACA,oBACA,kBAGF,kBACE,wBACA,gBAtPF,cA0PA,mBACE,YA3PF,cA6PE,mBA7PF,iBAiQA,qBACE,oCAGF,sBACE,gBACA,uBAGF,yBACE,kBACA",
"names": []
}
diff --git a/static/frontend/homepage/homepage.tmpl b/static/frontend/homepage/homepage.tmpl
index 384c996..9d09063 100644
--- a/static/frontend/homepage/homepage.tmpl
+++ b/static/frontend/homepage/homepage.tmpl
@@ -10,66 +10,122 @@

{{define "main"}}
<main class="go-Container" id="main-content">
- <div class="go-Content go-Content--center">
- <img class="Homepage-logo" width="700" height="300"
- src="/static/shared/gopher/package-search-700x300.jpeg" alt="Cartoon gopher typing">
- <form class="go-InputGroup Homepage-search Homepage-search--symbol"
- action="/search" role="search" data-gtmc="homepage search form">
- <input
- class="go-Input js-searchFocus"
- data-test-id="homepage-search"
- id="AutoComplete"
- role="textbox"
- aria-label="{{.SearchPrompt}}"
- aria-describedby="SearchTipContent"
- type="search"
- name="q"
- placeholder="{{.SearchPrompt}}"
- autocapitalize="off"
- autocomplete="off"
- autocorrect="off"
- spellcheck="false"
- title="{{.SearchPrompt}}"
- autofocus="true">
- <button type="submit" class="go-Button">Search</button>
- </form>
- <section class="go-Carousel Homepage-tips js-carousel" aria-label="Search Tips Carousel" data-slide-index="{{.TipIndex}}">
- <ul>
- {{range $i, $v := .SearchTips}}
- <li class="go-Carousel-slide" {{if not (eq $.TipIndex $i)}}aria-hidden{{end}} {{if (eq $.TipIndex $i)}}id="SearchTipContent"{{end}}>
- <p>
- <strong>Tip:</strong> {{.Text}}
- <a href="/search?q={{$v.Example1}}">“{{$v.Example1}}”</a> or
- <a href="/search?q={{$v.Example2}}">“{{$v.Example2}}”</a>.
- <a href="/search-help" target="_blank" rel="noopener" class="Homepage-helpLink">
- Search help <span><img width="24" height="24" src="/static/shared/icon/launch_gm_grey_24dp.svg" alt=""></span>
- </a>
- </p>
- </li>
- {{end}}
- </ul>
- </section>
- {{if .LocalModules}}
- <section class="Homepage-modules" aria-label="Local Modules">
- <div class="Homepage-modules-header">Or browse local modules:</div>
+ {{if .LocalModules}}
+ <div class="go-Content Homepage-local">
+ <form class="go-InputGroup Homepage-search Homepage-search--symbol Homepage-search--local"
+ action="/search" role="search" data-gtmc="homepage search form">
+ <input
+ class="go-Input js-searchFocus"
+ data-test-id="homepage-search"
+ id="AutoComplete"
+ role="textbox"
+ aria-label="{{.SearchPrompt}}"
+ type="search"
+ name="q"
+ placeholder="{{.SearchPrompt}}"
+ autocapitalize="off"
+ autocomplete="off"
+ autocorrect="off"
+ spellcheck="false"
+ title="{{.SearchPrompt}}"
+ autofocus="true">
+ <button type="submit" class="go-Button">Search</button>
+ </form>
+
+ <section class="Homepage-localSection Homepage-mainModule" aria-label="Local Modules">
+ <h2>Local Modules</h2>
<ul>
- {{range .LocalModules}}<li><a href="/{{.ModulePath}}">{{.ModulePath}}</a> &ndash; {{.Dir}}</li>{{end}}
+ {{range .LocalModules}}
+ <li>
+ <a href="/{{.ModulePath}}">{{.ModulePath}}</a>
+ <small>{{.Dir}}</small>
+ </li>
+ {{end}}
</ul>
</section>
- {{end}}
- </div>
+
+ {{if .DirectDependencies}}
+ <section class="Homepage-localSection Homepage-dependencies" aria-label="Dependencies">
+ <h2>Dependencies</h2>
+ <ul>
+ {{range .DirectDependencies}}
+ <li><a href="/{{.ModulePath}}">{{.ModulePath}}</a></li>
+ {{end}}
+ </ul>
+ </section>
+ {{end}}
+
+ {{if .IndirectDependencies}}
+ <details class="Homepage-localSection Homepage-transitive">
+ <summary>Indirect Dependencies ({{len .IndirectDependencies}})</summary>
+ <ul>
+ {{range .IndirectDependencies}}
+ <li><a href="/{{.ModulePath}}">{{.ModulePath}}</a></li>
+ {{end}}
+ </ul>
+ </details>
+ {{end}}
+
+ <section class="Homepage-localSection Homepage-stdlib" aria-label="Standard Library">
+ <a href="/std">Browse Standard Library</a>
+ </section>
+ </div>
+ {{else}}
+ <div class="go-Content go-Content--center">
+ <img class="Homepage-logo" width="700" height="300"
+ src="/static/shared/gopher/package-search-700x300.jpeg" alt="Cartoon gopher typing">
+ <form class="go-InputGroup Homepage-search Homepage-search--symbol"
+ action="/search" role="search" data-gtmc="homepage search form">
+ <input
+ class="go-Input js-searchFocus"
+ data-test-id="homepage-search"
+ id="AutoComplete"
+ role="textbox"
+ aria-label="{{.SearchPrompt}}"
+ aria-describedby="SearchTipContent"
+ type="search"
+ name="q"
+ placeholder="{{.SearchPrompt}}"
+ autocapitalize="off"
+ autocomplete="off"
+ autocorrect="off"
+ spellcheck="false"
+ title="{{.SearchPrompt}}"
+ autofocus="true">
+ <button type="submit" class="go-Button">Search</button>
+ </form>
+ <section class="go-Carousel Homepage-tips js-carousel" aria-label="Search Tips Carousel" data-slide-index="{{.TipIndex}}">
+ <ul>
+ {{range $i, $v := .SearchTips}}
+ <li class="go-Carousel-slide" {{if not (eq $.TipIndex $i)}}aria-hidden{{end}} {{if (eq $.TipIndex $i)}}id="SearchTipContent"{{end}}>
+ <p>
+ <strong>Tip:</strong> {{.Text}}
+ <a href="/search?q={{$v.Example1}}">“{{$v.Example1}}”</a> or
+ <a href="/search?q={{$v.Example2}}">“{{$v.Example2}}”</a>.
+ <a href="/search-help" target="_blank" rel="noopener" class="Homepage-helpLink">
+ Search help <span><img width="24" height="24" src="/static/shared/icon/launch_gm_grey_24dp.svg" alt=""></span>
+ </a>
+ </p>
+ </li>
+ {{end}}
+ </ul>
+ </section>
+ </div>
+ {{end}}
</main>
{{end}}

{{define "pre-footer"}}
- <div class="Questions">
- <div class="Questions-content">
- <div class="Questions-header" role="heading" aria-level="2">Frequently asked questions:</div>
- <ul>
- <li><a href="https://go.dev/about#adding-a-package">How can I add a package?</a></li>
- <li><a href="https://go.dev/about#removing-a-package">How can I remove a package?</a></li>
- <li><a href="https://go.dev/about#creating-a-badge">How can I add a go badge in my README file?</a></li>
- </ul>
+ {{if not .LocalModules}}
+ <div class="Questions">
+ <div class="Questions-content">
+ <div class="Questions-header" role="heading" aria-level="2">Frequently asked questions:</div>
+ <ul>
+ <li><a href="https://go.dev/about#adding-a-package">How can I add a package?</a></li>
+ <li><a href="https://go.dev/about#removing-a-package">How can I remove a package?</a></li>
+ <li><a href="https://go.dev/about#creating-a-badge">How can I add a go badge in my README file?</a></li>
+ </ul>
+ </div>
</div>
- </div>
+ {{end}}
{{end}}

Change information

Files:
  • M cmd/internal/pkgsite/server.go
  • M cmd/internal/pkgsite/server_test.go
  • M internal/frontend/homepage.go
  • M internal/frontend/server.go
  • M static/frontend/homepage/homepage.css
  • M static/frontend/homepage/homepage.min.css
  • M static/frontend/homepage/homepage.min.css.map
  • M static/frontend/homepage/homepage.tmpl
Change size: L
Delta: 8 files changed, 338 insertions(+), 88 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
  • requirement is not satisfiedkokoro-CI-Passes
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: pkgsite
Gerrit-Branch: master
Gerrit-Change-Id: I3a83800a6a5160f4a1f1d75b50028b816a6a6964
Gerrit-Change-Number: 737281
Gerrit-PatchSet: 1
Gerrit-Owner: Filippo Valsorda <fil...@golang.org>
Gerrit-Reviewer: Filippo Valsorda <fil...@golang.org>
unsatisfied_requirement
satisfied_requirement
open
diffy

Gopher Robot (Gerrit)

unread,
2:09 PM (5 hours ago) 2:09 PM
to Filippo Valsorda, goph...@pubsubhelper.golang.org, kokoro, Go LUCI, golang-co...@googlegroups.com
Attention needed from Filippo Valsorda

Message from Gopher Robot

Congratulations on opening your first change. Thank you for your contribution!

Next steps:
A maintainer will review your change and provide feedback. See
https://go.dev/doc/contribute#review for more info and tips to get your
patch through code review.

Most changes in the Go project go through a few rounds of revision. This can be
surprising to people new to the project. The careful, iterative review process
is our way of helping mentor contributors and ensuring that their contributions
have a lasting impact.

Open in Gerrit

Related details

Attention is currently required from:
  • Filippo Valsorda
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
  • requirement is not satisfiedkokoro-CI-Passes
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: pkgsite
Gerrit-Branch: master
Gerrit-Change-Id: I3a83800a6a5160f4a1f1d75b50028b816a6a6964
Gerrit-Change-Number: 737281
Gerrit-PatchSet: 1
Gerrit-Owner: Filippo Valsorda <fil...@golang.org>
Gerrit-Reviewer: Filippo Valsorda <fil...@golang.org>
Gerrit-CC: Gopher Robot <go...@golang.org>
Gerrit-CC: kokoro <noreply...@google.com>
Gerrit-Attention: Filippo Valsorda <fil...@golang.org>
Gerrit-Comment-Date: Sat, 17 Jan 2026 19:09:54 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: No
unsatisfied_requirement
satisfied_requirement
open
diffy

Filippo Valsorda (Gerrit)

unread,
2:11 PM (5 hours ago) 2:11 PM
to Filippo Valsorda, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
Attention needed from Filippo Valsorda

Filippo Valsorda uploaded new patchset

Filippo Valsorda uploaded patch set #2 to this change.
Open in Gerrit

Related details

Attention is currently required from:
  • Filippo Valsorda
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
  • requirement is not satisfiedkokoro-CI-Passes
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newpatchset
Gerrit-Project: pkgsite
Gerrit-Branch: master
Gerrit-Change-Id: I3a83800a6a5160f4a1f1d75b50028b816a6a6964
Gerrit-Change-Number: 737281
Gerrit-PatchSet: 2
unsatisfied_requirement
satisfied_requirement
open
diffy

kokoro (Gerrit)

unread,
2:11 PM (5 hours ago) 2:11 PM
to Filippo Valsorda, goph...@pubsubhelper.golang.org, Go LUCI, Gopher Robot, golang-co...@googlegroups.com
Attention needed from Filippo Valsorda

kokoro voted kokoro-CI-1

Kokoro presubmit build finished with status: FAILURE
Logs at: https://source.cloud.google.com/results/invocations/45a9e967-a1c9-4ce8-a359-0da93d1ea069

kokoro-CI-1
Open in Gerrit

Related details

Attention is currently required from:
  • Filippo Valsorda
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
  • requirement is not satisfiedkokoro-CI-Passes
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: pkgsite
Gerrit-Branch: master
Gerrit-Change-Id: I3a83800a6a5160f4a1f1d75b50028b816a6a6964
Gerrit-Change-Number: 737281
Gerrit-PatchSet: 1
Gerrit-Owner: Filippo Valsorda <fil...@golang.org>
Gerrit-Reviewer: Filippo Valsorda <fil...@golang.org>
Gerrit-Reviewer: kokoro <noreply...@google.com>
Gerrit-CC: Gopher Robot <go...@golang.org>
Gerrit-CC: kokoro <noreply...@google.com>
Gerrit-Attention: Filippo Valsorda <fil...@golang.org>
Gerrit-Comment-Date: Sat, 17 Jan 2026 19:11:00 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
unsatisfied_requirement
satisfied_requirement
open
diffy

kokoro (Gerrit)

unread,
2:14 PM (5 hours ago) 2:14 PM
to Filippo Valsorda, goph...@pubsubhelper.golang.org, Go LUCI, Gopher Robot, golang-co...@googlegroups.com
Attention needed from Filippo Valsorda

kokoro voted kokoro-CI-1

Kokoro presubmit build finished with status: FAILURE

Open in Gerrit

Related details

Attention is currently required from:
  • Filippo Valsorda
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
  • requirement is not satisfiedkokoro-CI-Passes
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: pkgsite
Gerrit-Branch: master
Gerrit-Change-Id: I3a83800a6a5160f4a1f1d75b50028b816a6a6964
Gerrit-Change-Number: 737281
Gerrit-PatchSet: 2
Gerrit-Owner: Filippo Valsorda <fil...@golang.org>
Gerrit-Reviewer: Filippo Valsorda <fil...@golang.org>
Gerrit-Reviewer: kokoro <noreply...@google.com>
Gerrit-CC: Gopher Robot <go...@golang.org>
Gerrit-CC: kokoro <noreply...@google.com>
Gerrit-Attention: Filippo Valsorda <fil...@golang.org>
Gerrit-Comment-Date: Sat, 17 Jan 2026 19:14:24 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
unsatisfied_requirement
satisfied_requirement
open
diffy
Reply all
Reply to author
Forward
0 new messages