Modern systems need to be able to self-adapt to changes in user needs, and changes affecting the system itself or its environment. Examples of systems demanding self-adaptive capabilities include mobile devices applications, which should deal with environmental changes, service-oriented systems that should replace unreliable services on-the-fly, and cyber-physical systems that should be resilient under uncertainties. The provision of rigorous techniques and tools to support adaptation so that it can be performed at runtime is challenging. It is necessary, for instance, an architecture and runtime support for dynamic monitoring, analysis, plan synthesis and plan execution. The first half of this talk will provide a retrospective of our prior work on the realization of dynamic variability in dynamic software product line solutions. The second half of the talk will cover more recent work focusing on automated plan generation and execution under uncertainty.