feat(registry): add DCNTRLIZED_DEV/GITEA_URL seam for dev registry
This commit is contained in:
@@ -13,6 +13,14 @@ services:
|
|||||||
dockerfile: Dockerfile.debug
|
dockerfile: Dockerfile.debug
|
||||||
environment:
|
environment:
|
||||||
- DEV_MODE=true
|
- DEV_MODE=true
|
||||||
|
- DCNTRLIZED_DEV=true
|
||||||
|
- GITEA_URL=${GITEA_URL:-http://192.168.122.184:3000}
|
||||||
|
- GITEA_REGISTRY_RO_TOKEN=${GITEA_REGISTRY_RO_TOKEN}
|
||||||
|
- GITEA_RW_PACKAGE_TOKEN=${GITEA_RW_PACKAGE_TOKEN}
|
||||||
|
- GITEA_ORG=${GITEA_ORG:-Dcntrlized}
|
||||||
|
- GITEA_USER=${GITEA_USER:-admin}
|
||||||
|
- GIT_TOKEN=${GIT_TOKEN}
|
||||||
|
- REGISTRY_USER=${REGISTRY_USER:-admin}
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
dcntrlized_net:
|
dcntrlized_net:
|
||||||
|
|||||||
+4
-1
@@ -18,8 +18,11 @@ services:
|
|||||||
- GITEA_REGISTRY_RO_TOKEN=${GITEA_REGISTRY_RO_TOKEN}
|
- GITEA_REGISTRY_RO_TOKEN=${GITEA_REGISTRY_RO_TOKEN}
|
||||||
- GITEA_RW_PACKAGE_TOKEN=${GITEA_RW_PACKAGE_TOKEN}
|
- GITEA_RW_PACKAGE_TOKEN=${GITEA_RW_PACKAGE_TOKEN}
|
||||||
- GITEA_ORG=${GITEA_ORG:-Dcntrlized}
|
- GITEA_ORG=${GITEA_ORG:-Dcntrlized}
|
||||||
- GITEA_USER=${GITEA_USER:-Admin}
|
- GITEA_USER=${GITEA_USER:-admin}
|
||||||
|
- GITEA_URL=${GITEA_URL:-http://192.168.122.184:3000}
|
||||||
|
- DCNTRLIZED_DEV=${DCNTRLIZED_DEV:-true}
|
||||||
- GIT_TOKEN=${GIT_TOKEN}
|
- GIT_TOKEN=${GIT_TOKEN}
|
||||||
|
- REGISTRY_USER=${REGISTRY_USER:-admin}
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
dcntrlized_net:
|
dcntrlized_net:
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ components:
|
|||||||
example: "0.0.1"
|
example: "0.0.1"
|
||||||
image:
|
image:
|
||||||
type: string
|
type: string
|
||||||
example: "git.dcntrlized.org/Dcntrlized/keepnote/keepnote:0.0.1"
|
example: "192.168.122.184:3000/dcntrlized/keepnote:dev"
|
||||||
digest:
|
digest:
|
||||||
type: string
|
type: string
|
||||||
title:
|
title:
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ The mechanism is a Git-backed, decentralized service registry: services are publ
|
|||||||
- Live state flows over WebSocket (`ws://127.0.0.1:8080/api/ws`); the catalog is fetched once from `/api/registry`.
|
- Live state flows over WebSocket (`ws://127.0.0.1:8080/api/ws`); the catalog is fetched once from `/api/registry`.
|
||||||
- Real-time statuses come from Docker (running, exited, stopped, created, restarting) plus UI states (installed, uninstalled).
|
- Real-time statuses come from Docker (running, exited, stopped, created, restarting) plus UI states (installed, uninstalled).
|
||||||
- Service metadata (title, vendor, author, description, source, licenses, revision) comes from OCI annotations published with each image.
|
- Service metadata (title, vendor, author, description, source, licenses, revision) comes from OCI annotations published with each image.
|
||||||
- Upstream registry is git.dcntrlized.org (Gitea), org `Dcntrlized`.
|
- Upstream registry defaults to git.dcntrlized.org (Gitea), org `Dcntrlized`;
|
||||||
|
in dev (`DCNTRLIZED_DEV=true`) it targets `GITEA_URL` (the dev VM
|
||||||
|
`192.168.122.184:3000`).
|
||||||
- Maestro itself runs as a container (image `maestro`); its own container is hidden from the list.
|
- Maestro itself runs as a container (image `maestro`); its own container is hidden from the list.
|
||||||
- Update detection compares the installed version against the registry latest via semver; versions are normalized to `X.Y.Z`.
|
- Update detection compares the installed version against the registry latest via semver; versions are normalized to `X.Y.Z`.
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default defineConfig(({ command }): UserConfig => {
|
|||||||
? {
|
? {
|
||||||
'/api': 'http://127.0.0.1:8080',
|
'/api': 'http://127.0.0.1:8080',
|
||||||
'/gitea-api': {
|
'/gitea-api': {
|
||||||
target: 'https://git.dcntrlized.org', // Your Gitea base URL
|
target: process.env.GITEA_URL || 'https://git.dcntrlized.org', // Gitea base URL (override with GITEA_URL in dev)
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/gitea-api/, ''),
|
rewrite: (path) => path.replace(/^\/gitea-api/, ''),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import (
|
|||||||
|
|
||||||
func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||||
// 1. Query Gitea REST API using the exact Org name
|
// 1. Query Gitea REST API using the exact Org name
|
||||||
apiURL := fmt.Sprintf("https://git.dcntrlized.org/api/v1/packages/%s?type=container", os.Getenv("GITEA_ORG"))
|
apiURL := fmt.Sprintf("%s/api/v1/packages/%s?type=container", giteaBaseURL(), os.Getenv("GITEA_ORG"))
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(r.Context(), http.MethodGet, apiURL, nil)
|
req, err := http.NewRequestWithContext(r.Context(), http.MethodGet, apiURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -150,7 +150,7 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
|||||||
// 4. Fetch OCI metadata only for the highest version of each package
|
// 4. Fetch OCI metadata only for the highest version of each package
|
||||||
for _, pkg := range latestPackages {
|
for _, pkg := range latestPackages {
|
||||||
pkgNameLower := strings.ToLower(pkg.Name)
|
pkgNameLower := strings.ToLower(pkg.Name)
|
||||||
imageRef := fmt.Sprintf("git.dcntrlized.org/%s/%s:%s", ociOrg, pkgNameLower, pkg.Version)
|
imageRef := fmt.Sprintf("%s/%s/%s:%s", registryHost(), ociOrg, pkgNameLower, pkg.Version)
|
||||||
|
|
||||||
// The Gitea package API does not link org-level container packages to a
|
// The Gitea package API does not link org-level container packages to a
|
||||||
// repository, so the repository URL is resolved from the image's OCI
|
// repository, so the repository URL is resolved from the image's OCI
|
||||||
@@ -162,7 +162,11 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
|||||||
CreatedAt: pkg.CreatedAt,
|
CreatedAt: pkg.CreatedAt,
|
||||||
}
|
}
|
||||||
|
|
||||||
ref, err := name.ParseReference(imageRef)
|
var refOpts []name.Option
|
||||||
|
if isInsecureRegistry() {
|
||||||
|
refOpts = append(refOpts, name.Insecure)
|
||||||
|
}
|
||||||
|
ref, err := name.ParseReference(imageRef, refOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to parse image reference %s: %v", imageRef, err)
|
logger.Error("Failed to parse image reference %s: %v", imageRef, err)
|
||||||
registryItems = append(registryItems, item)
|
registryItems = append(registryItems, item)
|
||||||
@@ -284,11 +288,48 @@ func GetRegistry(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// repoURLFromImageRef derives the repository browse URL from a container image
|
// repoURLFromImageRef derives the repository browse URL from a container image
|
||||||
// reference of the form host/org/repo:tag (https://host/org/repo).
|
// reference of the form host/org/repo:tag (scheme://host/org/repo), using the
|
||||||
|
// scheme of the configured Gitea base URL.
|
||||||
func repoURLFromImageRef(imageRef string) string {
|
func repoURLFromImageRef(imageRef string) string {
|
||||||
ref, err := name.ParseReference(imageRef)
|
ref, err := name.ParseReference(imageRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return "https://" + ref.Context().RegistryStr() + "/" + ref.Context().RepositoryStr()
|
return giteaScheme() + "://" + ref.Context().RegistryStr() + "/" + ref.Context().RepositoryStr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// giteaBaseURL returns the Gitea instance base URL (scheme://host[:port]).
|
||||||
|
// Production defaults to git.dcntrlized.org; dev mode (DCNTRLIZED_DEV=true)
|
||||||
|
// overrides it with GITEA_URL when set.
|
||||||
|
func giteaBaseURL() string {
|
||||||
|
if os.Getenv("DCNTRLIZED_DEV") == "true" {
|
||||||
|
if u := strings.TrimRight(os.Getenv("GITEA_URL"), "/"); u != "" {
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "https://git.dcntrlized.org"
|
||||||
|
}
|
||||||
|
|
||||||
|
// registryHost strips the scheme from the Gitea base URL, returning just the
|
||||||
|
// host[:port] used in container image references.
|
||||||
|
func registryHost() string {
|
||||||
|
base := giteaBaseURL()
|
||||||
|
if i := strings.Index(base, "://"); i >= 0 {
|
||||||
|
return base[i+3:]
|
||||||
|
}
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
|
||||||
|
// isInsecureRegistry reports whether the Gitea registry is served over plain
|
||||||
|
// HTTP, in which case image references must be parsed with name.Insecure.
|
||||||
|
func isInsecureRegistry() bool {
|
||||||
|
return strings.HasPrefix(giteaBaseURL(), "http://")
|
||||||
|
}
|
||||||
|
|
||||||
|
// giteaScheme returns the scheme (http/https) of the configured Gitea base URL.
|
||||||
|
func giteaScheme() string {
|
||||||
|
if i := strings.Index(giteaBaseURL(), "://"); i >= 0 {
|
||||||
|
return giteaBaseURL()[:i]
|
||||||
|
}
|
||||||
|
return "https"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user