From c714932ea6b3e7ffcc49bd3c0e102c0ba5dd76c2 Mon Sep 17 00:00:00 2001 From: An Nguyen Date: Mon, 19 Feb 2024 13:23:18 -0600 Subject: [PATCH] add github workflow to sync envs to bitrise as well as local script to fetch envs from aws --- .github/workflows/bitrise-envs-sync.yml | 48 +++++++++++++++ packages/core-mobile/package.json | 1 + .../scripts/common/writeEnvsToFile.sh | 32 ++++++++++ packages/core-mobile/scripts/getEnvs.sh | 52 ++++++++++++++++ .../scripts/github/uploadEnvsToBitrise.sh | 61 +++++++++++++++++++ 5 files changed, 194 insertions(+) create mode 100644 .github/workflows/bitrise-envs-sync.yml create mode 100755 packages/core-mobile/scripts/common/writeEnvsToFile.sh create mode 100755 packages/core-mobile/scripts/getEnvs.sh create mode 100755 packages/core-mobile/scripts/github/uploadEnvsToBitrise.sh diff --git a/.github/workflows/bitrise-envs-sync.yml b/.github/workflows/bitrise-envs-sync.yml new file mode 100644 index 0000000000..4c9faf8194 --- /dev/null +++ b/.github/workflows/bitrise-envs-sync.yml @@ -0,0 +1,48 @@ +name: Bitrise Envs Sync + +on: + pull_request: + # The branches below must be a subset of the branches above + branches: ['development'] + workflow_dispatch: + +jobs: + upload-envs-to-bitrise: + name: Upload envs to Bitrise + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + + steps: + - name: Check out repo + uses: actions/checkout@v3 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + aws-region: us-east-2 + role-to-assume: arn:aws:iam::975050371175:role/github-sa-role + role-session-name: githubsa + + - name: Get envs from AWS + uses: aws-actions/aws-secretsmanager-get-secrets@v1 + with: + secret-ids: | + ENV_DEV, core/dev/mobile/.env.development + ENV_DEV_E2E, core/dev/mobile/.env.development.e2e + ENV_PROD, core/dev/mobile/.env.production + ENV_PROD_E2E, core/dev/mobile/.env.production.e2e + + - name: Wrtie envs to files + working-directory: packages/core-mobile/scripts/github + run: | + ../common/writeEnvsToFile.sh "$ENV_DEV" ".env.development" + ../common/writeEnvsToFile.sh "$ENV_DEV_E2E" ".env.development.e2e" + ../common/writeEnvsToFile.sh "$ENV_PROD" ".env.production" + ../common/writeEnvsToFile.sh "$ENV_PROD_E2E" ".env.production.e2e" + + - name: Upload envs to Bitrise + working-directory: packages/core-mobile/scripts/github + run: | + ./uploadEnvsToBitrise.sh ${{ secrets.BITRISE_ACCESS_TOKEN }} diff --git a/packages/core-mobile/package.json b/packages/core-mobile/package.json index cdd4d3da31..0d6e5ca89a 100644 --- a/packages/core-mobile/package.json +++ b/packages/core-mobile/package.json @@ -3,6 +3,7 @@ "private": true, "scripts": { "setup": "yarn allow-scripts", + "envs": "./scripts/getEnvs.sh", "android": "ENVFILE=.env.development react-native run-android --variant=internalDebug", "podInstall": "bundle _2.1.4_ install && cd ios && bundle exec pod install", "ios": "ENVFILE=.env.development react-native run-ios", diff --git a/packages/core-mobile/scripts/common/writeEnvsToFile.sh b/packages/core-mobile/scripts/common/writeEnvsToFile.sh new file mode 100755 index 0000000000..149dce5913 --- /dev/null +++ b/packages/core-mobile/scripts/common/writeEnvsToFile.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -e + +# Check if the correct number of parameters are provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Retrieve the env value and assign it to the data variable +data=$1 + +output_file=$2 + +# Check if the secret value is empty +if [ -z "$data" ]; then + echo "Error: Failed to retrieve secret value" + exit 1 +fi + +# Parse the string to extract key-value pairs +pairs=$(echo "$data" | sed 's/[{}"]//g' | tr ',' '\n' | sed 's/:/=/') + +# Erase the content of the output file +> "$output_file" + +# Write the key-value pairs to the output file +echo "$pairs" | while IFS= read -r line; do + echo "$line" | sed 's/\\//g' >> "$output_file" +done + +echo "envs saved to $output_file" \ No newline at end of file diff --git a/packages/core-mobile/scripts/getEnvs.sh b/packages/core-mobile/scripts/getEnvs.sh new file mode 100755 index 0000000000..dc4c510969 --- /dev/null +++ b/packages/core-mobile/scripts/getEnvs.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Retrieve secret by id from AWS Secrets Manager +getSecretFromAWS() { + local secret_id="$1" + sudo aws secretsmanager get-secret-value --secret-id "$secret_id" | grep SecretString | sed 's/.*"SecretString": "\(.*\)".*/\1/' +} + +# Check if a AWS profile exists +awsConfigurationExists() { + local profile_name="${1}" + local profile_status=$( (sudo aws configure --profile ${1} list) 2>&1) + + if [[ $profile_status = *'could not be found'* ]]; then + return 1 + else + return 0 + fi +} + +# Check if profile "default" exists. If not, ask to create one +if ! $(awsConfigurationExists "default"); then + echo 'Profile "default" does not exist. Please create one first!' + sudo aws configure sso +fi + +# Check if the session is still valid. If not, ask to re-login +ACCOUNT=$(sudo aws sts get-caller-identity --query "Account") + +# Account is valid if account is a 12 digit account number plus surrounding double-quotes +if [ ${#ACCOUNT} -ne 14 ]; then + echo 'logging in with profile "default"' + sudo aws sso login --profile default +fi + +# Retrieve all envs from AWS +echo "retrieving envs from AWS Secrets Manager..." +ENV_DEV=$(getSecretFromAWS "core/dev/mobile/.env.development") +ENV_DEV_E2E=$(getSecretFromAWS "core/dev/mobile/.env.development.e2e") +ENV_PROD=$(getSecretFromAWS "core/dev/mobile/.env.production") +ENV_PROD_E2E=$(getSecretFromAWS "core/dev/mobile/.env.production.e2e") + +# Write to .env files +./scripts/common/writeEnvsToFile.sh "$ENV_DEV" ".env.development" +./scripts/common/writeEnvsToFile.sh "$ENV_DEV_E2E" ".env.development.e2e" +./scripts/common/writeEnvsToFile.sh "$ENV_PROD" ".env.production" +./scripts/common/writeEnvsToFile.sh "$ENV_PROD_E2E" ".env.production.e2e" + +# Use .env.development as the default +cp .env.development .env +echo ".env.development copied to .env" +echo "envs successfully retrieved and saved 🥳" diff --git a/packages/core-mobile/scripts/github/uploadEnvsToBitrise.sh b/packages/core-mobile/scripts/github/uploadEnvsToBitrise.sh new file mode 100755 index 0000000000..38d44f20fe --- /dev/null +++ b/packages/core-mobile/scripts/github/uploadEnvsToBitrise.sh @@ -0,0 +1,61 @@ +#!/bin/bash +set -e + +# Get the value of a key +function getJsonVal () { + python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))"; +} + +# Search for a value when key matches the provided condition +function searchJsonVal () { + python -c " +import json, sys + +# Load JSON data from stdin +data = json.load(sys.stdin)['data'] + +# Filter data based on the provided condition +filtered_data = [x for x in data if x.get('$1') == '$2'] + +# Print the filtered data as JSON +sys.stdout.write(json.dumps(filtered_data)) +" +} + +# Check if the correct number of parameters are provided +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +app_slug="7d7ca5af7066e290" +file_name="env-files.zip" +bitrise_file_name=ENV_FILES +access_token=$1 +base_url="https://api.bitrise.io/v0.1/apps/$app_slug" + +# get all generic profile files +# if the bitrise_file_name already exists, delete it +all_files=$(curl -X GET -H "Authorization: $access_token" "$base_url/generic-project-files") +existing_file_slug=$( echo $all_files | searchJsonVal "user_env_key" $bitrise_file_name | getJsonVal "[0]['slug']" | tr -d '"') +curl -X DELETE "$base_url/generic-project-files/$existing_file_slug" -H "Authorization: $access_token" + +# compress all env files into a single zip file +zip $file_name .env.* + +# upload the zip file to bitrise https://devcenter.bitrise.io/en/api/managing-files-in-generic-file-storage.html + +# 1. create a temporary pre-signed upload URL +file_size=$(ls -l $file_name | awk '{print $5}') +response_1=$(curl -H "Authorization: $access_token" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"upload_file_name\": \"$file_name\", \"upload_file_size\": $file_size, \"user_env_key\": \"$bitrise_file_name\"}" -X POST "$base_url/generic-project-files") + +# 2. upload the file to the pre-signed URL +upload_url=$( echo $response_1 | getJsonVal "['data']['upload_url']" | tr -d '"' ) + +curl -T $file_name $upload_url + +# 3. confirm the file upload +file_slug=$( echo $response_1 | getJsonVal "['data']['slug']" | tr -d '"' ) +curl -X POST -H "Authorization: $access_token" "$base_url/generic-project-files/$file_slug/uploaded" + +echo "envs uploaded to bitrise successfully" \ No newline at end of file