checker: also consider WIP zone for tidy, scheduler, and auto-fill
Some checks are pending
continuous-integration/drone/push Build is pending

Tidy and scheduler now check both the WIP zone ([0]) and the latest
published zone ([1]) so that services being drafted are not cleaned up
or ignored by the scheduler.  Auto-fill searches WIP first for the
best user experience when configuring new services.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
nemunaire 2026-04-15 21:34:31 +07:00
commit e5a8c55630
3 changed files with 50 additions and 26 deletions

View file

@ -505,24 +505,24 @@ func (u *CheckerOptionsUsecase) buildAutoFillContext(
ctx[happydns.AutoFillDomainName] = domain.DomainName
// Load the latest published zone from domain history (index 0 is WIP).
if len(domain.ZoneHistory) < 2 {
// Load the WIP zone ([0]) for auto-fill context, so the user can
// configure checkers for services they are currently working on.
if len(domain.ZoneHistory) == 0 {
return ctx, nil
}
latestZoneId := domain.ZoneHistory[1]
zone, err := u.autoFillStore.GetZone(latestZoneId)
zone, err := u.autoFillStore.GetZone(domain.ZoneHistory[0])
if err != nil {
return ctx, fmt.Errorf("loading zone for auto-fill: %w", err)
}
ctx[happydns.AutoFillZone] = zone
// Resolve service if target has a ServiceId.
// Search from the latest published zone forward through history.
// Search WIP first, then latest published, then older history.
if serviceId := happydns.TargetIdentifier(target.ServiceId); serviceId != nil {
for i := 1; i < len(domain.ZoneHistory); i++ {
for i := 0; i < len(domain.ZoneHistory); i++ {
z := zone
if i > 1 {
if i > 0 {
z, err = u.autoFillStore.GetZone(domain.ZoneHistory[i])
if err != nil {
continue

View file

@ -674,20 +674,33 @@ func (s *Scheduler) loadAllDomains() []*happydns.Domain {
}
func (s *Scheduler) loadDomainServices(domain *happydns.Domain) []*happydns.ServiceMessage {
if s.zoneStore == nil || len(domain.ZoneHistory) < 2 {
return nil
}
latestZoneID := domain.ZoneHistory[1]
zone, err := s.zoneStore.GetZone(latestZoneID)
if err != nil {
log.Printf("Scheduler: failed to load zone %s for domain %s: %v", latestZoneID, domain.DomainName, err)
if s.zoneStore == nil || len(domain.ZoneHistory) == 0 {
return nil
}
// Collect services from the WIP zone ([0]) and the latest published
// zone ([1]). This lets the scheduler pick up new services the user
// is configuring while still covering what is live.
seen := make(map[string]struct{})
var services []*happydns.ServiceMessage
for _, svcs := range zone.Services {
services = append(services, svcs...)
for _, idx := range []int{0, 1} {
if idx >= len(domain.ZoneHistory) {
break
}
zone, err := s.zoneStore.GetZone(domain.ZoneHistory[idx])
if err != nil {
log.Printf("Scheduler: failed to load zone %s for domain %s: %v", domain.ZoneHistory[idx], domain.DomainName, err)
continue
}
for _, svcs := range zone.Services {
for _, svc := range svcs {
key := svc.Id.String()
if _, dup := seen[key]; !dup {
seen[key] = struct{}{}
services = append(services, svc)
}
}
}
}
return services
}

View file

@ -223,16 +223,27 @@ func (tu *tidyUpUsecase) TidyCheckerConfigurations() error {
return err
}
if cfg.ServiceId != nil && len(domain.ZoneHistory) > 1 {
zone, err := tu.store.GetZone(domain.ZoneHistory[1])
if err != nil {
return err
}
if cfg.ServiceId != nil && len(domain.ZoneHistory) > 0 {
// Check both the WIP zone ([0]) and the latest published
// zone ([1]) so we keep configs for services that are
// either being worked on or currently live.
found := false
for _, svcs := range zone.Services {
for _, svc := range svcs {
if svc.Id.Equals(*cfg.ServiceId) {
found = true
for _, idx := range []int{0, 1} {
if idx >= len(domain.ZoneHistory) {
break
}
zone, err := tu.store.GetZone(domain.ZoneHistory[idx])
if err != nil {
return err
}
for _, svcs := range zone.Services {
for _, svc := range svcs {
if svc.Id.Equals(*cfg.ServiceId) {
found = true
break
}
}
if found {
break
}
}