Skip to content

Instantly share code, notes, and snippets.

@ryan-blunden
Created July 9, 2021 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryan-blunden/ec01ca1245022314d14f42c28a3d5c31 to your computer and use it in GitHub Desktop.
Save ryan-blunden/ec01ca1245022314d14f42c28a3d5c31 to your computer and use it in GitHub Desktop.
Doppler Cloudflare Pages Secrets Sync

Doppler Cloudflare Pages Secrets Sync Script

NOTE: This script is a work in progress

Bash script to sync secrets from Doppler to Cloudflare Pages using the Pages Update Project API.

Usage

The following enviroment variables must be set or else you will be prompted when running the script:

  • CLOUDFLARE_ACCOUNT_ID: Account Id
  • CLOUDFLARE_EMAIL: Account email
  • CLOUDFLARE_GLOBAL_API_KEY: Must be the global API key as APi token permissions don't yet exist
  • CLOUDFLARE_PAGES_NAME: Name of pages application
  • CLOUDFLARE_PAGES_ENVIRONMENT: Either "production" or "preview"

You can also optionally set the following environment variables for additional behavior:

  • IMPORT_CLOUDFLARE=yes: Will import the current environment variables from Cloudflare to Doppler before syncing (should only need this once)
  • CLEAN_SYNC=yes: Doppler is the source of truth and any environment variables not in Doppler will be deleted
  • AUTO_DEPLOY: Trigger a deploy in order to apply the environment variable updates
#!/usr/bin/env bash
log () {
case $1 in
info)
echo -e "\n\e[92m[info]: $2"
;;
warn)
echo -e "\n\e[93m[warn]: $2"
;;
error)
echo -e "\n\e[91m[error]: $2"
;;
*)
echo -e "\n\e[92m[$1]: $2"
esac
}
log info 'Confirming Doppler Project and Config'
doppler setup --silent
DOPPLER_PROJECT=$(doppler configure get project --plain)
DOPPLER_CONFIG=$(doppler configure get config --plain)
log info "Selected $DOPPLER_PROJECT > $DOPPLER_CONFIG"
if [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
echo -en '\nCLOUDFLARE_ACCOUNT_ID: ' && read -s CLOUDFLARE_ACCOUNT_ID
fi
if [ -z "$CLOUDFLARE_EMAIL" ]; then
echo -en '\nCLOUDFLARE_EMAIL: ' && read -s CLOUDFLARE_EMAIL
fi
if [ -z "$CLOUDFLARE_GLOBAL_API_KEY" ]; then
echo -en '\nCLOUDFLARE_GLOBAL_API_KEY: ' && read -s CLOUDFLARE_GLOBAL_API_KEY
fi
if [ -z "$CLOUDFLARE_PAGES_NAME" ]; then
echo -en '\nCLOUDFLARE_PAGES_NAME: ' && read -s CLOUDFLARE_PAGES_NAME
fi
if [ -z "$CLOUDFLARE_PAGES_ENVIRONMENT" ]; then
echo -en '\nCLOUDFLARE_PAGES_ENVIRONMENT: ' && read CLOUDFLARE_PAGES_ENVIRONMENT
fi
export CLOUDFLARE_PAGES_ENVIRONMENT
if [[ $CLOUDFLARE_PAGES_ENVIRONMENT != "production" ]] && [[ $CLOUDFLARE_PAGES_ENVIRONMENT != "preview" ]]
then
log error 'The CLOUDFLARE_PAGES_ENVIRONMENT must be either "production" or "preview"\n'
exit 1
fi
curl --silent --fail -X GET "https://api.cloudflare.com/client/v4/user" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
-H "X-Auth-Key: $CLOUDFLARE_GLOBAL_API_KEY" \
-H "Content-Type: application/json" > /dev/null
if [[ $? -ne 0 ]]; then
log error "Sorry, the supplied Cloudflare credentials appear to be invalid\n"
exit 1
fi
CLOUDFLARE_PAGE_URL="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$CLOUDFLARE_PAGES_NAME"
cloudflare_deploy () {
curl --fail --silent -X $1 "$CLOUDFLARE_PAGE_URL/deployments" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
-H "X-Auth-Key: $CLOUDFLARE_GLOBAL_API_KEY" \
-H "Content-Type: application/json"
}
cloudflare_env_vars () {
if [[ -n "$2" ]]; then
curl --fail --silent -X PATCH "$CLOUDFLARE_PAGE_URL" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
-H "X-Auth-Key: $CLOUDFLARE_GLOBAL_API_KEY" \
-H "Content-Type: application/json" \
--data "$2";
else
curl --fail --silent -X $1 "$CLOUDFLARE_PAGE_URL" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
-H "X-Auth-Key: $CLOUDFLARE_GLOBAL_API_KEY" \
-H "Content-Type: application/json";
fi
}
env_vars_payload () {
echo "{\"deployment_configs\":{\"$1\":{\"env_vars\":$2}}}"
}
cloudflare_env_vars GET > /dev/null
if [[ $? -ne 0 ]]; then
log error "Sorry, a Pages app '$CLOUDFLARE_PAGES_NAME' belonging to Account Id '$CLOUDFLARE_ACCOUNT_ID' could not be found.\n"
exit 1
fi
if [[ -n "$IMPORT_CLOUDFLARE" ]]; then
log info "\$IMPORT_CLOUDFLARE set: Importing secrets from $CLOUDFLARE_PAGES_NAME $CLOUDFLARE_PAGES_ENVIRONMENT to Doppler"
doppler secrets upload <(jq -cr '.result.deployment_configs.production.env_vars | with_entries(.value |= .value)' <(cloudflare_env_vars GET))
fi
if [[ -n "$CLEAN_SYNC" ]]; then
log info "\$CLEAN_SYNC set: Deleting all $CLOUDFLARE_PAGES_NAME $CLOUDFLARE_PAGES_ENVIRONMENT envirionment variables"
NULL_ENV_VARS=$(jq -cr '.result | select(.deployment_configs == "production") | .env_vars | with_entries(.value |= null)' <(cloudflare_env_vars GET))
cloudflare_env_vars PATCH "$(env_vars_payload production "$NULL_ENV_VARS")" > /dev/null
fi
log info "Syncing secrets from $(doppler configure get project --plain) > $(doppler configure get config --plain) to $CLOUDFLARE_PAGES_NAME $CLOUDFLARE_PAGES_ENVIRONMENT environment"
DOPPLER_SECRETS=$(jq -cr '. | with_entries(.value = { "value": (.value)})' <(doppler secrets download --no-file --format json))
RESPONSE=$(cloudflare_env_vars PATCH "$(env_vars_payload production "$DOPPLER_SECRETS")")
log info 'Done!'
jq -r '.result.deployment_configs' <(echo "$RESPONSE")
if [[ -n "$AUTO_DEPLOY" ]]; then
log info "\$AUTO_DEPLOY set: Triggering deploy so environment variable updates are applied"
cloudflare_deploy POST > /dev/null
if [[ $? -eq 0 ]]; then
log info "Deployment triggered successfully\n"
else
log error "Deployment failed. Please check your Cloudflare Pages deployment logs\n"
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment