From f0f90384600235e94535ebf0e43429ce02f378c8 Mon Sep 17 00:00:00 2001 From: Kiril Keranov <114745615+kiril-keranov@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:22:13 +0300 Subject: [PATCH 01/11] Refactor Play Framework detection logic --- src/java/containers/play.go | 105 +++++++++++++++--------------------- 1 file changed, 44 insertions(+), 61 deletions(-) diff --git a/src/java/containers/play.go b/src/java/containers/play.go index 0ef20af50..1a727642e 100644 --- a/src/java/containers/play.go +++ b/src/java/containers/play.go @@ -31,41 +31,48 @@ func (p *PlayContainer) Detect() (string, error) { p.context.Log.Debug("Play: Checking buildDir: %s", buildDir) - // First, validate that we don't have ambiguous configuration (hybrid apps) - if err := p.Validate(); err != nil { - p.context.Log.Debug("Play: Validation failed: %v", err) - return "", err - } - - // Try to detect Play Framework type in order of specificity - // Order matters to avoid ambiguous detection - // Check staged apps (more specific - lib/staged only) before dist apps (less specific - has start scripts) - - // 1. Try Pre22Staged (Play 2.0-2.1 staged app - only staged/ with JARs) - p.context.Log.Debug("Play: Trying Pre22Staged detection") - if p.detectPre22Staged(buildDir) { - p.context.Log.Info("Play: Detected Pre22Staged - version %s", p.playVersion) - return "Play", nil - } - - // 2. Try Post22Staged (Play 2.2+ staged app - only lib/ with JARs) - p.context.Log.Debug("Play: Trying Post22Staged detection") - if p.detectPost22Staged(buildDir) { - p.context.Log.Info("Play: Detected Post22Staged - version %s", p.playVersion) - return "Play", nil + // Run each detector once, collecting matches. Using a temporary container per + // detector avoids mutating p until we know exactly one type matched. + type candidate struct { + name string + c *PlayContainer + } + var matches []candidate + + detectors := []struct { + name string + fn func(*PlayContainer, string) bool + }{ + {"Pre22Staged", (*PlayContainer).detectPre22Staged}, + {"Post22Staged", (*PlayContainer).detectPost22Staged}, + {"Post22Dist", (*PlayContainer).detectPost22Dist}, + {"Pre22Dist", (*PlayContainer).detectPre22Dist}, + } + + for _, d := range detectors { + p.context.Log.Debug("Play: Trying %s detection", d.name) + tmp := &PlayContainer{context: p.context} + if d.fn(tmp, buildDir) { + p.context.Log.Debug("Play: %s matched (version %s)", d.name, tmp.playVersion) + matches = append(matches, candidate{d.name, tmp}) + } } - // 3. Try Post22Dist (Play 2.2+ distributed app in application-root/bin) - p.context.Log.Debug("Play: Trying Post22Dist detection") - if p.detectPost22Dist(buildDir) { - p.context.Log.Info("Play: Detected Post22Dist - version %s", p.playVersion) - return "Play", nil + if len(matches) > 1 { + names := make([]string, len(matches)) + for i, m := range matches { + names[i] = m.name + } + return "", fmt.Errorf("Play Framework application version cannot be determined: %v", names) } - // 4. Try Pre22Dist (Play 2.0-2.1 distributed app in application-root/) - p.context.Log.Debug("Play: Trying Pre22Dist detection") - if p.detectPre22Dist(buildDir) { - p.context.Log.Info("Play: Detected Pre22Dist - version %s", p.playVersion) + if len(matches) == 1 { + m := matches[0] + p.playType = m.c.playType + p.playVersion = m.c.playVersion + p.startScript = m.c.startScript + p.libDir = m.c.libDir + p.context.Log.Info("Play: Detected %s - version %s", m.name, p.playVersion) return "Play", nil } @@ -73,6 +80,12 @@ func (p *PlayContainer) Detect() (string, error) { return "", nil } +// Validate checks for ambiguous Play configurations without mutating the receiver. +func (p *PlayContainer) Validate() error { + _, err := p.Detect() + return err +} + // detectPost22Dist detects Play 2.2+ distributed applications // Structure: application-root/bin/