A config.json.template holds placeholders:
{ "apiUrl": "${API_URL}", "region": "${REGION}" }
Jenkinsfile:
pipeline {
agent { label 'node22' }
stages {
stage('Build') {
steps {
sh 'npm ci && npx ng build --configuration production'
stash name: 'dist', includes: 'dist/**'
}
}
stage('Deploy') {
matrix {
axes { axis { name 'REGION'; values 'ap-south-1', 'eu-west-1', 'us-east-1' } }
stages {
stage('Publish') {
steps {
unstash 'dist'
withAWS(role: 'ui-deployer', roleAccount: '111122223333', region: "${REGION}") {
script {
def urls = [ 'ap-south-1': 'https://api-in.example.com',
'eu-west-1': 'https://api-eu.example.com',
'us-east-1': 'https://api-us.example.com' ]
env.API_URL = urls[REGION]
}
sh """
envsubst < config.json.template > dist/browser/config.json
aws s3 sync dist/browser s3://acme-ui-$REGION --delete --exclude config.json
aws s3 cp dist/browser/config.json s3://acme-ui-$REGION/config.json --cache-control no-cache
"""
}
}
}
}
}
}
}
}
Add aws cloudfront create-invalidation --paths "/index.html" "/config.json" per region. Use a role with s3:PutObject on those buckets only, and ask for approval before the production regions.