generated from mathias/template-go-web
feat(gitea): surface mathias's own open Gitea issues on stage 03 (#4)
TDD: IssueNodes parses /repos/issues/search into stage nodes (title, repo tag, clickable html_url). gitea.MyIssues() reads GITEA_TOKEN and skips gracefully when unset, mirroring the existing liveOverlay fallback pattern. Single-operator homelab, not per-visitor OAuth: a static read-only PAT gates on "cleared Authentik forward-auth", not per-user token exchange — see #4 discussion. GITEA_TOKEN provisioning in infra (ExternalSecret) is a separate follow-up; without it the overlay is inert (no crash, just no live nodes), so this ships safely ahead of that wiring. Nodes with a url now render as clickable <a class="node"> instead of <div class="node">.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -21,9 +22,37 @@ func base() string {
|
||||
|
||||
// Runs returns the raw /actions/tasks JSON for mathias/cad-atlas (newest first).
|
||||
func Runs() ([]byte, error) {
|
||||
url := base() + "/api/v1/repos/mathias/cad-atlas/actions/tasks?limit=50"
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
resp, err := client.Get(url) //nolint:noctx // short-lived, timeout on the client
|
||||
return get(base()+"/api/v1/repos/mathias/cad-atlas/actions/tasks?limit=50", "")
|
||||
}
|
||||
|
||||
// MyIssues returns the raw /repos/issues/search JSON for the token owner's
|
||||
// own open issues across every repo they can see. Requires GITEA_TOKEN — a
|
||||
// read-only PAT for the mathias account (this is a single-operator homelab,
|
||||
// not per-visitor OAuth: anyone who clears Authentik forward-auth sees
|
||||
// Mathias's own data). Returns an error if GITEA_TOKEN is unset, so callers
|
||||
// can skip the overlay gracefully.
|
||||
func MyIssues() ([]byte, error) {
|
||||
token := os.Getenv("GITEA_TOKEN")
|
||||
if token == "" {
|
||||
return nil, fmt.Errorf("GITEA_TOKEN not set")
|
||||
}
|
||||
url := base() + "/api/v1/repos/issues/search?state=open&created=true&type=issues&limit=8"
|
||||
return get(url, token)
|
||||
}
|
||||
|
||||
// get performs a short-lived GET, optionally with a bearer token, and returns
|
||||
// the response body.
|
||||
func get(url, token string) ([]byte, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if token != "" {
|
||||
req.Header.Set("Authorization", "token "+token)
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -33,7 +62,7 @@ func Runs() ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("gitea runs: %s", resp.Status)
|
||||
return nil, fmt.Errorf("gitea: %s", resp.Status)
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user