Compare commits

..

1 Commits

Author SHA1 Message Date
unkinben 808015f6bb fix: prune RPM metadata when a local file is evicted
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
Evicting or deleting a local RPM removed the local_files row but left its
rpm_metadata behind, so generated repodata kept listing a package that no
longer exists. Deletes now run a provider cleanup hook symmetric to the
existing upload hook.

- add PostDeleteHook and MetadataDeleter provider interfaces, plus a
  DeleteRPMMetadata DB method
- implement AfterDelete in the RPM provider to drop the metadata row
- route both local delete paths (evictLocal and the files handler) through
  a shared deleteLocalFile helper that removes the file then runs the hook
- cover the cleanup with a dockerised test
2026-07-03 14:50:04 +10:00
2 changed files with 2 additions and 28 deletions
-7
View File
@@ -95,7 +95,6 @@ func (s *Server) routes() chi.Router {
r.Get("/health", s.handleHealth)
r.Get("/", s.handleRoot)
r.Get("/version", s.handleVersion)
proxyHandler := v1.NewProxyHandler(s.engine, s.virtEngine, s.db, s.store, s.localHandler)
r.Mount("/api/v1", proxyHandler.Routes())
@@ -144,13 +143,7 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"status":"ok"}`)
}
// handleRoot sends browsers landing on the bare domain to the web UI, which is
// served under /ui. The service identity that used to live here is at /version.
func (s *Server) handleRoot(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/ui/", http.StatusFound)
}
func (s *Server) handleVersion(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{"name":"artifactapi","version":"%s"}`, s.version)
+2 -21
View File
@@ -129,32 +129,13 @@ func req(t *testing.T, method, path string, body string) (*http.Response, []byte
return resp, b
}
// reqNoRedirect issues a request without following redirects so the response's
// status and Location header can be asserted directly.
func reqNoRedirect(t *testing.T, method, path string) *http.Response {
t.Helper()
rq, _ := http.NewRequest(method, testTS.URL+path, nil)
client := &http.Client{CheckRedirect: func(*http.Request, []*http.Request) error {
return http.ErrUseLastResponse
}}
resp, err := client.Do(rq)
if err != nil {
t.Fatalf("%s %s: %v", method, path, err)
}
resp.Body.Close()
return resp
}
func TestServerHealthAndRoot(t *testing.T) {
requireStack(t)
if resp, _ := req(t, "GET", "/health", ""); resp.StatusCode != 200 {
t.Errorf("health: %d", resp.StatusCode)
}
if resp := reqNoRedirect(t, "GET", "/"); resp.StatusCode != http.StatusFound || resp.Header.Get("Location") != "/ui/" {
t.Errorf("root redirect: %d %q", resp.StatusCode, resp.Header.Get("Location"))
}
if resp, b := req(t, "GET", "/version", ""); resp.StatusCode != 200 || !strings.Contains(string(b), "test-version") {
t.Errorf("version: %d %s", resp.StatusCode, b)
if resp, b := req(t, "GET", "/", ""); resp.StatusCode != 200 || !strings.Contains(string(b), "test-version") {
t.Errorf("root: %d %s", resp.StatusCode, b)
}
if resp, _ := req(t, "GET", "/api/v2/health", ""); resp.StatusCode != 200 {
t.Errorf("health v2: %d", resp.StatusCode)