Split listing support: Gitea and Radicle as separate apps
- setup: with RUNNER_DIR, fetch the runner registration token from Gitea's admin API (POST /admin/actions/runners/registration-token) instead of the gitea CLI on Gitea's volume; record secrets/setup-status (ok, unreachable, bad-credentials) and exit cleanly when Gitea cannot be used. - mirror: Radicle is optional. Repositories wait until a node is there (key and control socket in RAD_HOME), re-checked every reconcile; RADICLE=off. - page: /status.json; hide the Radicle parts without a node, banner when Gitea is unreachable or refuses the login. - example workflow: runs-on: ipcr, the forge's own runner label. - docs: two listings, split (IPCR-Forge) and all in one (IPCR-Forge-AIO).
This commit is contained in:
+26
-1
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//go:embed web
|
||||
@@ -13,7 +14,7 @@ var webFiles embed.FS
|
||||
// webHandler serves the forge's public page. Everything on it is public anyway: links, the
|
||||
// documentation, IPCR's list of published images (public on IPFS) and the list of mirrored
|
||||
// repositories (public on Radicle). Nothing here changes anything.
|
||||
func webHandler(st *state, publishedFile string) *http.ServeMux {
|
||||
func webHandler(st *state, publishedFile string, status func() siteStatus) *http.ServeMux {
|
||||
mux := http.NewServeMux()
|
||||
page, _ := webFiles.ReadFile("web/index.html")
|
||||
icon, _ := webFiles.ReadFile("web/icon.png")
|
||||
@@ -42,12 +43,36 @@ func webHandler(st *state, publishedFile string) *http.ServeMux {
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
json.NewEncoder(w).Encode(st.list())
|
||||
})
|
||||
mux.HandleFunc("GET /status.json", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
json.NewEncoder(w).Encode(status())
|
||||
})
|
||||
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("ok\n"))
|
||||
})
|
||||
return mux
|
||||
}
|
||||
|
||||
// siteStatus is what the page needs to know about the apps the forge relies on: Gitea (as the
|
||||
// setup step last found it) and whether a Radicle node is there to mirror into.
|
||||
type siteStatus struct {
|
||||
Gitea string `json:"gitea"` // ok | unreachable | bad-credentials | unknown (setup has not run)
|
||||
Radicle bool `json:"radicle"`
|
||||
}
|
||||
|
||||
// readSetupStatus reads what the setup step left in SECRETS_DIR/setup-status.
|
||||
func readSetupStatus(secrets string) string {
|
||||
var s struct {
|
||||
Gitea string `json:"gitea"`
|
||||
}
|
||||
b, err := os.ReadFile(filepath.Join(secrets, "setup-status"))
|
||||
if err != nil || json.Unmarshal(b, &s) != nil || s.Gitea == "" {
|
||||
return "unknown"
|
||||
}
|
||||
return s.Gitea
|
||||
}
|
||||
|
||||
// adminRoutes adds the admin pages: the page itself (signed-in Gitea admins only), the login, and
|
||||
// the API it calls.
|
||||
func adminRoutes(mux *http.ServeMux, au *auth, adm *adminAPI) {
|
||||
|
||||
Reference in New Issue
Block a user