Description
The Use case
This problem is more clear with an example use case:
Say I have following environments
- 1
Production
server visible to world - 1
Staging
server visible to clients - 1
Dev
server visible to developers - N
Local
servers specific to individual developers say around 30 developers.
The project is using Git
version control. To deploy or to load a project the developer had to do following things
git clone <repository_url>/project
cd project
gradle bootstrap <env_name>
gradle build -x test
gradle bootRun
It was easier to do because application.properties
was git ignored and running gradle bootstrap <env_name>
generated inside it spring.profiles.active=<env_name>
. If provided <env_name> didn't exist a new profile with name application-local_<env_name>.properties
was created from the template application-local.properties
. The developer was free to choose from a set of properties for their specific needs. Thus building a configuration was as easy as writing code using spring.profiles.include
.
What changed
The new profile processing has put a new set of restrictions which is unable to answer a very simple problem i.e. given a constraint, a feature and a requirement like
- Constraint: No developer should commit their local configurations in repository.
- Feature: Every developer should have their own configurations.
- Requirement: All configurations for
production
,staging
anddev
should be tracked lets say themmajor configurations
.
Lets try to address this problem
Trial 1:
Use profile groups by putting all major configurations in application.yml
. Let user specify active profile and its configuration.
- Local configuration starts being tracked
Trial 2:
Add default spring.profiles.active=this_env
in application.yml
and make it mandatory for user to create this file and add their customization there.
- Now user can't reference any of the configuration in
application.yml
and has to copy whole thing again in their configuration. BecauseThe spring.profile.group property cannot be used in profile-specific documents.
- If we are using
activate.on-profile
then developers will be forced to use a set of rules.
Trial 3:
Make application.yml.example
with all contents and let developer copy and override it. Which is quit rough work.
I am unable to find a proper solution to this problem, but for more understanding I am explaining my current set up so someone can guide how to address the problem if I am missing something .
Project files
└── resources
├── config
│ ├── .gitignore
│ ├── application-common_pg.properties
│ ├── application-common.properties
│ ├── application-local_monkeycoder.properties
│ ├── application-local_pg_customized.properties
│ ├── application-local.properties
│ ├── application-prod.properties
│ ├── application.properties
│ ├── application.properties.example
│ ├── application-security.properties
│ ├── application-security.properties.example
│ └── application-stage.properties
├── db
│ └── migration
├── META-INF
│ └── spring-configuration-metadata.json
├── static
└── templates
.gitignore
has
application-security.properties
application.properties
application-local_*.properties
application.properties.example
has
spring.profiles.active=stage
application-common.properties
has things like
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration
application-common_pg.properties
has
spring.jpa.properties.hibernate.dialect=com.hello.hibernate.dialect.PostgreSQL13Dialect
application-security.properties.example
has passwords and others have their own data source urls. For example
application-prod.properties
has at top
spring.profiles.include=common,security,common-pg
logging.level.web=info
# ....
This is very difficult to migrate to the new structure I can't think of an idea without breaking one or two things.