Repository: quarkusio/quarkus
Issue: 2.0 dev mode not reading application properties

## Describe the bug
After switching to `2.0`, it looks like dev mode is not reading my `application.yaml` in `config/`.

### Expected behavior
Successful run

### Actual behavior
`NoSuchElementException: SRCFG00014: The config property name is required but it could not be found in any config source`

## To Reproduce

Reproducer: `service1` after swapping the Quarkus version in https://github.com/mweber03/quarkus-test

Steps to reproduce the behavior:
1. Switch to `2.0.1.Final` in `gradle.properties`
2. `./gradlew service1:quarkusDev`

### Output of `uname -a` or `ver`
Ubuntu 20.04

### Output of `java -version`
OpenJDK 11.0.11

### Quarkus version or git rev
2.0.1

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)
Gradle 6.9


Changed files:
core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java
core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java
core/deployment/src/main/java/io/quarkus/deployment/steps/ProfileBuildStep.java
extensions/config-yaml/deployment/src/main/java/io/quarkus/config/yaml/deployment/ConfigYamlProcessor.java
core/deployment/src/main/java/io/quarkus/deployment/steps/DevModeBuildStep.java

diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java
index 6220c8e3578..1bef9fda0fb 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java
@@ -959,6 +959,44 @@ Set<String> checkForFileChange(Function<DevModeContext.ModuleInfo, DevModeContex
                     }
                 }
             }
+
+            // Mostly a copy of the code above but to handle watched files that are set with absolute path (not in the app resources)
+            for (String watchedFilePath : timestampSet.watchedFilePaths.keySet()) {
+                Path watchedFile = Paths.get(watchedFilePath);
+                if (watchedFile.isAbsolute()) {
+                    if (watchedFile.toFile().exists()) {
+                        try {
+                            long value = Files.getLastModifiedTime(watchedFile).toMillis();
+                            Long existing = timestampSet.watchedFileTimestamps.get(watchedFile);
+                            //existing can be null when running tests
+                            //as there is both normal and test resources, but only one set of watched timestampts
+                            if (existing != null && value > existing) {
+                                ret.add(watchedFilePath);
+                                //a write can be a 'truncate' + 'write'
+                                //if the file is empty we may be seeing the middle of a write
+                                if (Files.size(watchedFile) == 0) {
+                                    try {
+                                        Thread.sleep(200);
+                                    } catch (InterruptedException e) {
+                                        //ignore
+                                    }
+                                }
+                                //re-read, as we may have read the original TS if the middle of
+                                //a truncate+write, even if the write had completed by the time
+                                //we read the size
+                                value = Files.getLastModifiedTime(watchedFile).toMillis();
+
+                                log.infof("File change detected: %s", watchedFile);
+                                timestampSet.watchedFileTimestamps.put(watchedFile, value);
+                            }
+                        } catch (IOException e) {
+                            throw new UncheckedIOException(e);
+                        }
+                    } else {
+                        timestampSet.watchedFileTimestamps.put(watchedFile, 0L);
+                    }
+                }
+            }
         }
 
         return ret;
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java
index 05d28cf9222..accc69537ed 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java
@@ -3,12 +3,15 @@
 import static io.quarkus.deployment.steps.ConfigBuildSteps.SERVICES_PREFIX;
 import static io.quarkus.deployment.util.ServiceUtil.classNamesNamedIn;
 import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix;
+import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS;
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toSet;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.lang.reflect.Modifier;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -20,6 +23,7 @@
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import org.apache.commons.io.FilenameUtils;
 import org.eclipse.microprofile.config.Config;
 import org.eclipse.microprofile.config.ConfigProvider;
 import org.eclipse.microprofile.config.spi.ConfigSource;
@@ -38,6 +42,7 @@
 import io.quarkus.deployment.builditem.ConfigurationTypeBuildItem;
 import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
 import io.quarkus.deployment.builditem.GeneratedResourceBuildItem;
+import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
 import io.quarkus.deployment.builditem.LaunchModeBuildItem;
 import io.quarkus.deployment.builditem.LiveReloadBuildItem;
 import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem;
@@ -58,10 +63,12 @@
 import io.quarkus.runtime.annotations.StaticInitSafe;
 import io.quarkus.runtime.configuration.ConfigRecorder;
 import io.quarkus.runtime.configuration.ConfigUtils;
+import io.quarkus.runtime.configuration.ProfileManager;
 import io.quarkus.runtime.configuration.RuntimeOverrideConfigSource;
 import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix;
 import io.smallrye.config.ConfigSourceFactory;
 import io.smallrye.config.PropertiesLocationConfigSourceFactory;
+import io.smallrye.config.SmallRyeConfig;
 
 public class ConfigGenerationBuildStep {
 
@@ -217,6 +224,47 @@ public void setupConfigOverride(
         }
     }
 
+    @BuildStep
+    public void watchConfigFiles(BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
+        List<String> configWatchedFiles = new ArrayList<>();
+
+        SmallRyeConfig config = (SmallRyeConfig) ConfigProvider.getConfig();
+        String userDir = System.getProperty("user.dir");
+
+        // Main files
+        configWatchedFiles.add("application.properties");
+        configWatchedFiles.add("META-INF/microprofile-config.properties");
+        configWatchedFiles.add(Paths.get(userDir, ".env").toAbsolutePath().toString());
+        configWatchedFiles.add(Paths.get(userDir, "config", "application.properties").toAbsolutePath().toString());
+
+        // Profiles
+        String profile = ProfileManager.getActiveProfile();
+        configWatchedFiles.add(String.format("application-%s.properties", profile));
+        configWatchedFiles.add(String.format("META-INF/microprofile-config-%s.properties", profile));
+        configWatchedFiles.add(Paths.get(userDir, String.format(".env-%s", profile)).toAbsolutePath().toString());
+        configWatchedFiles.add(
+                Paths.get(userDir, "config", String.format("application-%s.properties", profile)).toAbsolutePath().toString());
+
+        Optional<List<String>> optionalLocations = config.getOptionalValues(SMALLRYE_CONFIG_LOCATIONS, String.class);
+        optionalLocations.ifPresent(locations -> {
+            for (String location : locations) {
+                if (!Files.isDirectory(Paths.get(location))) {
+                    configWatchedFiles.add(location);
+                    configWatchedFiles.add(appendProfileToFilename(location, profile));
+                }
+            }
+        });
+
+        for (String configWatchedFile : configWatchedFiles) {
+            watchedFiles.produce(new HotDeploymentWatchedFileBuildItem(configWatchedFile));
+        }
+    }
+
+    private String appendProfileToFilename(String path, String activeProfile) {
+        String pathWithoutExtension = FilenameUtils.removeExtension(path);
+        return String.format("%s-%s.%s", pathWithoutExtension, activeProfile, FilenameUtils.getExtension(path));
+    }
+
     private void handleMembers(Config config, Map<String, String> values, Iterable<ClassDefinition.ClassMember> members,
             String prefix, Set<String> excludedConfigKeys) {
         for (ClassDefinition.ClassMember member : members) {
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/DevModeBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/DevModeBuildStep.java
index ebdaed9d9b0..7ff4aa47ffe 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/steps/DevModeBuildStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/DevModeBuildStep.java
@@ -1,30 +1,17 @@
 package io.quarkus.deployment.steps;
 
-import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS;
-
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
 
-import org.eclipse.microprofile.config.ConfigProvider;
-
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
 import io.quarkus.runtime.LiveReloadConfig;
 
 class DevModeBuildStep {
-
     @BuildStep
     List<HotDeploymentWatchedFileBuildItem> watchChanges(LiveReloadConfig liveReloadConfig) {
         List<String> names = new ArrayList<>();
-        names.add("META-INF/microprofile-config.properties");
-        names.add("application.properties");
-        names.add(Paths.get(".env").toAbsolutePath().toString());
-        Optional<List<String>> locations = ConfigProvider.getConfig().getOptionalValues(SMALLRYE_CONFIG_LOCATIONS,
-                String.class);
-        locations.ifPresent(names::addAll);
         liveReloadConfig.watchedResources.ifPresent(names::addAll);
         return names.stream().map(HotDeploymentWatchedFileBuildItem::new).collect(Collectors.toList());
     }
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ProfileBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ProfileBuildStep.java
index 20400b34fb2..b3c6f5ce6e8 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ProfileBuildStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ProfileBuildStep.java
@@ -1,53 +1,17 @@
 package io.quarkus.deployment.steps;
 
-import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_LOCATIONS;
-
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.Optional;
-
-import org.apache.commons.io.FilenameUtils;
-import org.eclipse.microprofile.config.ConfigProvider;
-
-import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
 import io.quarkus.deployment.builditem.LaunchModeBuildItem;
 import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem;
 import io.quarkus.runtime.LaunchMode;
 
 public class ProfileBuildStep {
-
     @BuildStep
     RunTimeConfigurationDefaultBuildItem defaultProfile(LaunchModeBuildItem launchModeBuildItem) {
         return new RunTimeConfigurationDefaultBuildItem("quarkus.profile",
                 getProfileValue(launchModeBuildItem.getLaunchMode()));
     }
 
-    @BuildStep
-    void watchProfileSpecificFile(LaunchModeBuildItem launchModeBuildItem,
-            BuildProducer<HotDeploymentWatchedFileBuildItem> items) {
-        String activeProfile = getProfileValue(launchModeBuildItem.getLaunchMode());
-        String suffixedApplicationProperties = String.format("application-%s.properties", activeProfile);
-        items.produce(new HotDeploymentWatchedFileBuildItem(suffixedApplicationProperties));
-        items.produce(new HotDeploymentWatchedFileBuildItem(
-                Paths.get(String.format(".env-%s", activeProfile)).toAbsolutePath().toString()));
-        items.produce(new HotDeploymentWatchedFileBuildItem(Paths
-                .get(System.getProperty("user.dir"), "config", suffixedApplicationProperties).toAbsolutePath().toString()));
-        Optional<List<String>> locations = ConfigProvider.getConfig().getOptionalValues(SMALLRYE_CONFIG_LOCATIONS,
-                String.class);
-        if (locations.isPresent()) {
-            for (String location : locations.get()) {
-                items.produce(new HotDeploymentWatchedFileBuildItem(appendProfileToFilename(location, activeProfile)));
-            }
-        }
-    }
-
-    private String appendProfileToFilename(String path, String activeProfile) {
-        String pathWithoutExtension = FilenameUtils.removeExtension(path);
-        return String.format("%s-%s.%s", pathWithoutExtension, activeProfile, FilenameUtils.getExtension(path));
-    }
-
     private String getProfileValue(LaunchMode launchMode) {
         if (launchMode == LaunchMode.DEVELOPMENT) {
             return "dev";
diff --git a/extensions/config-yaml/deployment/src/main/java/io/quarkus/config/yaml/deployment/ConfigYamlProcessor.java b/extensions/config-yaml/deployment/src/main/java/io/quarkus/config/yaml/deployment/ConfigYamlProcessor.java
index 52532751421..870999bc842 100644
--- a/extensions/config-yaml/deployment/src/main/java/io/quarkus/config/yaml/deployment/ConfigYamlProcessor.java
+++ b/extensions/config-yaml/deployment/src/main/java/io/quarkus/config/yaml/deployment/ConfigYamlProcessor.java
@@ -1,5 +1,9 @@
 package io.quarkus.config.yaml.deployment;
 
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
 import io.quarkus.config.yaml.runtime.ApplicationYamlConfigSourceLoader;
 import io.quarkus.deployment.Feature;
 import io.quarkus.deployment.annotations.BuildProducer;
@@ -32,12 +36,27 @@ public void bootstrap(
     }
 
     @BuildStep
-    void watchYamlConfig(BuildProducer<HotDeploymentWatchedFileBuildItem> items) {
-        items.produce(new HotDeploymentWatchedFileBuildItem("application.yaml"));
-        items.produce(new HotDeploymentWatchedFileBuildItem("application.yml"));
+    void watchYamlConfig(BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
+        List<String> configWatchedFiles = new ArrayList<>();
+        String userDir = System.getProperty("user.dir");
+
+        // Main files
+        configWatchedFiles.add("application.yaml");
+        configWatchedFiles.add("application.yml");
+        configWatchedFiles.add(Paths.get(userDir, "config", "application.yaml").toAbsolutePath().toString());
+        configWatchedFiles.add(Paths.get(userDir, "config", "application.yml").toAbsolutePath().toString());
+
+        // Profiles
+        String profile = ProfileManager.getActiveProfile();
+        configWatchedFiles.add(String.format("application-%s.yaml", profile));
+        configWatchedFiles.add(String.format("application-%s.yml", profile));
+        configWatchedFiles
+                .add(Paths.get(userDir, "config", String.format("application-%s.yaml", profile)).toAbsolutePath().toString());
+        configWatchedFiles
+                .add(Paths.get(userDir, "config", String.format("application-%s.yml", profile)).toAbsolutePath().toString());
 
-        String activeProfile = ProfileManager.getActiveProfile();
-        items.produce(new HotDeploymentWatchedFileBuildItem(String.format("application-%s.yml", activeProfile)));
-        items.produce(new HotDeploymentWatchedFileBuildItem(String.format("application-%s.yaml", activeProfile)));
+        for (String configWatchedFile : configWatchedFiles) {
+            watchedFiles.produce(new HotDeploymentWatchedFileBuildItem(configWatchedFile));
+        }
     }
 }