Prevent Missing Configuration Values Across Environments
Why Is Configuration Management Difficult?
One recurrent issue during every deployment has been configuration.
In our company, we use Spring Boot, and configurations that differ by deployment environment are managed using Spring Cloud Config.
Typically, configurations in Spring are managed through application.yml, but the fundamental problem lies in the reflection of this configuration file.
In our company, deployments proceed in the following order: environments are divided into dev, qa, stage, and production, each with its unique configuration file.
The issue arises when any configuration is missed, potentially necessitating a redeployment or causing unreflected content in production due to a missing configuration file.
1. Creating Deployment Reviews
To resolve this, the initial thought was to have a review session before deployment.
The drawback to this approach is that it consumes everyone’s time and has high costs, so we currently only review added infrastructure or configuration before production deployment.
This approach was more effective in preventing missing configurations as multiple people reviewed it. However, scrutinizing each added part extended the review time.
2. Creating a Configuration File Comparison Action
The second approach we implemented was creating a bot to compare configuration files.
While there are YAML comparison tools available, they compare values entirely, which isn’t suitable for comparing files with environment-specific values.
Thus, we considered the following method:
- Extract only the Key values from the configuration files for each environment.
- Check for differences in types, missing keys on one side, or index differences in arrays, etc.
- Generate a report as a comment on the PR for merging branches of each environment if changes are detected.
This allows for accurate tracking of missing configurations across environments.
Design
The overall structure is fairly straightforward, and the basic setup is as follows. We implemented a CLI tool called yaml-diff-reporter, which parses and compares two YAML configuration files, exporting the report to the console or a file.
Usage instructions are included, so if you’re facing similar issues, feel free to use it. It is implemented to allow file comparison mode selection via flags.
Creating the Action
name: Configuration File Comparison
on:
pull_request:
branches: [ qa, stg, prod ]
As previously mentioned, we have four environments. Generally, during development, the code merges into dev, and for deployment, a PR for qa
, stg
, or prod
is created, hence the setup.
jobs:
config-check:
permissions:
contents: read
pull-requests: write
issues: write
env:
MERGE_FROM: ${{ github.event.pull_request.base.ref == 'qa' && 'dev' || (github.event.pull_request.base.ref == 'stg' && 'qa' || 'stg') }}
MERGE_TO: ${{ github.event.pull_request.base.ref }}
As our server operates in a Private Repository, permissions are granted for the bot token to write PR comments.
Moreover, the settings are arranged to compare dev with qa, and qa with stg based on the current environment, by setting MERGE_FROM and MERGE_TO environment variables.
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Install yaml-diff-reporter CLI
run: go install github.com/YangTaeyoung/yaml-diff-reporter@v1.0.0
Go is installed, followed by the yaml-diff-reporter
. Side note: Go makes it very convenient to install CLI tools with a simple install command.
- name: Download Config Files
uses: AcmeSoftwareLLC/github-downloader@v1
with:
git-pat: ${{ secrets.GH_TOKEN }}
repo: # Cloud Config Repository
ref: # Cloud Config Repository Branch
includes: |
{application yaml path}/${{ env.MERGE_FROM }}/application.yml:${{ env.MERGE_FROM }}.yml
{application yaml path}/${{ env.MERGE_TO }}/application.yml:${{ env.MERGE_TO }}.yml
Files are then downloaded from the specified path in the Github Repository. There are numerous existing download actions, so feel free to choose any that suit your needs.
- name: Compare Config Files
id: compare
run: |
DIFF_RESULT=$(yaml-diff-reporter -l ${{ env.MERGE_FROM }}.yml -r ${{ env.MERGE_TO }}.yml \
-la ${{ env.MERGE_FROM }} -ra ${{ env.MERGE_TO }} \
-M type -M key -M index \ # Specify mode (excluding value)
-I # Specify keys to ignore
-lang ko # Specify report output language, currently supports Korean (ko) and English (en)
-f markdown) # Specify report format: markdown, JSON, or plain text
echo "diff_result<<EOF" >> $GITHUB_OUTPUT
echo "${DIFF_RESULT}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
The downloaded files are compared using CLI, and the results are stored in the variable diff_result
, which is then specified as the output of the step.
The reason for using EOF is that reports are output in multiline format.
For a single line, something likeecho "diff_result=${DIFF_RESULT}"
would suffice.
- name: Create Result PR Comment
if: always()
uses: thollander/actions-comment-pull-request@v3
with:
message: |
# Configuration File Comparison Result
${{ steps.compare.outputs.diff_result == 'No differences found' && '' || '' }}
${{ steps.compare.outputs.diff_result }}
## File Reference
- [${{ env.MERGE_FROM }}.yml](Github file path)
- [${{ env.MERGE_TO }}.yml](Github file path)
- name: Handle Failure (On Differences)
if: steps.compare.outputs.diff_result != 'No differences found'
run: exit 1
The result is then written as a PR comment, and if it fails, the action is set to fail, preventing merging of the PR. You can also just output the report with ${{ steps.compare.outputs.diff_result }}
, but I decided to embellish it a bit.
Outcome
Sensitive internal information has been redacted, but the result shows comments in the PR indicating which keys have issues, making it easier to understand.
Drawbacks
This method also has a clear drawback. It only compares newly added keys, so if existing values are changed or modified, simple comparisons of keys or types alone won’t detect this.
As there is no perfect silver bullet, developers must continually strive, improve, and search for better solutions.