feat: add Go vanity import server and BugSETI CI pipeline
Add dappco.re vanity import handler (cmd/vanity-import/) that serves go-import meta tags, enabling `go get dappco.re/core` to resolve to forge.lthn.ai/host-uk/core. Deployed as a Docker container behind Traefik on snider-linux. Add Woodpecker CI pipeline (.woodpecker/bugseti.yml) for BugSETI cross-platform builds. Phase 1: Linux amd64 with CGO, triggered on bugseti-v* tags and main branch pushes to cmd/bugseti/. Closes #3, closes #9 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b74f8264d3
commit
49da5b10c3
4 changed files with 168 additions and 0 deletions
52
.woodpecker/bugseti.yml
Normal file
52
.woodpecker/bugseti.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
when:
|
||||
- event: tag
|
||||
ref: "refs/tags/bugseti-v*"
|
||||
- event: push
|
||||
branch: main
|
||||
path: "cmd/bugseti/**"
|
||||
|
||||
steps:
|
||||
- name: frontend
|
||||
image: node:22-bookworm
|
||||
commands:
|
||||
- cd cmd/bugseti/frontend
|
||||
- npm ci --prefer-offline
|
||||
- npm run build
|
||||
|
||||
- name: build-linux
|
||||
image: golang:1.25-bookworm
|
||||
environment:
|
||||
CGO_ENABLED: "1"
|
||||
GOOS: linux
|
||||
GOARCH: amd64
|
||||
commands:
|
||||
- apt-get update -qq && apt-get install -y -qq libgtk-3-dev libwebkit2gtk-4.1-dev > /dev/null 2>&1
|
||||
- cd cmd/bugseti
|
||||
- go build -tags production -trimpath -buildvcs=false -ldflags="-w -s" -o ../../bin/bugseti
|
||||
depends_on: [frontend]
|
||||
|
||||
- name: package
|
||||
image: alpine:3.21
|
||||
commands:
|
||||
- cd bin
|
||||
- tar czf bugseti-linux-amd64.tar.gz bugseti
|
||||
- sha256sum bugseti-linux-amd64.tar.gz > bugseti-linux-amd64.tar.gz.sha256
|
||||
- echo "=== Package ==="
|
||||
- ls -lh bugseti-linux-amd64.*
|
||||
- cat bugseti-linux-amd64.tar.gz.sha256
|
||||
depends_on: [build-linux]
|
||||
|
||||
- name: release
|
||||
image: plugins/gitea-release
|
||||
settings:
|
||||
api_key:
|
||||
from_secret: forgejo_token
|
||||
base_url: https://forge.lthn.ai
|
||||
files:
|
||||
- bin/bugseti-linux-amd64.tar.gz
|
||||
- bin/bugseti-linux-amd64.tar.gz.sha256
|
||||
title: ${CI_COMMIT_TAG}
|
||||
note: "BugSETI ${CI_COMMIT_TAG} — Linux amd64 build"
|
||||
when:
|
||||
- event: tag
|
||||
depends_on: [package]
|
||||
9
cmd/vanity-import/Dockerfile
Normal file
9
cmd/vanity-import/Dockerfile
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
FROM golang:1.25-alpine AS build
|
||||
WORKDIR /src
|
||||
COPY go.mod main.go ./
|
||||
RUN go build -trimpath -ldflags="-w -s" -o /vanity-import .
|
||||
|
||||
FROM alpine:3.21
|
||||
COPY --from=build /vanity-import /vanity-import
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/vanity-import"]
|
||||
3
cmd/vanity-import/go.mod
Normal file
3
cmd/vanity-import/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module dappco.re/vanity-import
|
||||
|
||||
go 1.25.6
|
||||
104
cmd/vanity-import/main.go
Normal file
104
cmd/vanity-import/main.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// Package main provides a Go vanity import server for dappco.re.
|
||||
//
|
||||
// When a Go tool requests ?go-get=1, this server responds with HTML
|
||||
// containing <meta name="go-import"> tags that map dappco.re module
|
||||
// paths to their Git repositories on forge.lthn.ai.
|
||||
//
|
||||
// For browser requests (no ?go-get=1), it redirects to the Forgejo
|
||||
// repository web UI.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var modules = map[string]string{
|
||||
"core": "host-uk/core",
|
||||
"build": "host-uk/build",
|
||||
}
|
||||
|
||||
const (
|
||||
forgeBase = "https://forge.lthn.ai"
|
||||
vanityHost = "dappco.re"
|
||||
defaultAddr = ":8080"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addr := os.Getenv("ADDR")
|
||||
if addr == "" {
|
||||
addr = defaultAddr
|
||||
}
|
||||
|
||||
// Allow overriding forge base URL
|
||||
forge := os.Getenv("FORGE_URL")
|
||||
if forge == "" {
|
||||
forge = forgeBase
|
||||
}
|
||||
|
||||
// Parse additional modules from VANITY_MODULES env (format: "mod1=owner/repo,mod2=owner/repo")
|
||||
if extra := os.Getenv("VANITY_MODULES"); extra != "" {
|
||||
for _, entry := range strings.Split(extra, ",") {
|
||||
parts := strings.SplitN(strings.TrimSpace(entry), "=", 2)
|
||||
if len(parts) == 2 {
|
||||
modules[parts[0]] = parts[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
http.HandleFunc("/", handler(forge))
|
||||
|
||||
log.Printf("vanity-import listening on %s (%d modules)", addr, len(modules))
|
||||
for mod, repo := range modules {
|
||||
log.Printf(" %s/%s → %s/%s.git", vanityHost, mod, forge, repo)
|
||||
}
|
||||
log.Fatal(http.ListenAndServe(addr, nil))
|
||||
}
|
||||
|
||||
func handler(forge string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Extract the first path segment as the module name
|
||||
path := strings.TrimPrefix(r.URL.Path, "/")
|
||||
if path == "" {
|
||||
// Root request — redirect to forge org page
|
||||
http.Redirect(w, r, forge+"/host-uk", http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Module is the first path segment (e.g., "core" from "/core/pkg/mcp")
|
||||
mod := strings.SplitN(path, "/", 2)[0]
|
||||
|
||||
repo, ok := modules[mod]
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// If go-get=1, serve the vanity import HTML
|
||||
if r.URL.Query().Get("go-get") == "1" {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
fmt.Fprintf(w, `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="go-import" content="%s/%s git %s/%s.git">
|
||||
<meta name="go-source" content="%s/%s %s/%s %s/%s/src/branch/main{/dir} %s/%s/src/branch/main{/dir}/{file}#L{line}">
|
||||
<meta http-equiv="refresh" content="0; url=%s/%s">
|
||||
</head>
|
||||
<body>
|
||||
Redirecting to <a href="%s/%s">%s/%s</a>...
|
||||
</body>
|
||||
</html>
|
||||
`, vanityHost, mod, forge, repo,
|
||||
vanityHost, mod, forge, repo, forge, repo, forge, repo,
|
||||
forge, repo,
|
||||
forge, repo, forge, repo)
|
||||
return
|
||||
}
|
||||
|
||||
// Browser request — redirect to Forgejo
|
||||
http.Redirect(w, r, forge+"/"+repo, http.StatusFound)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue