Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/android-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: Setup sample app environment
id: sample_env
if: ${{ !cancelled() }}
run: ${{ github.workspace }}/scripts/setup_storefront_env --skip-optional-prompts
run: ${{ github.workspace }}/scripts/setup_storefront_env
env:
STOREFRONT_DOMAIN: example.myshopify.com
STOREFRONT_ACCESS_TOKEN: test-token
Expand Down Expand Up @@ -113,7 +113,7 @@ jobs:
cache: 'gradle'

- name: Setup sample app environment
run: ${{ github.workspace }}/scripts/setup_storefront_env --skip-optional-prompts
run: ${{ github.workspace }}/scripts/setup_storefront_env
env:
STOREFRONT_DOMAIN: example.myshopify.com
STOREFRONT_ACCESS_TOKEN: test-token
Expand Down Expand Up @@ -146,7 +146,7 @@ jobs:
run: ./gradlew detekt

- name: Setup sample app environment
run: ${{ github.workspace }}/scripts/setup_storefront_env --skip-optional-prompts
run: ${{ github.workspace }}/scripts/setup_storefront_env
env:
STOREFRONT_DOMAIN: example.myshopify.com
STOREFRONT_ACCESS_TOKEN: test-token
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rn-test-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ jobs:
echo "JAVA_HOME: $JAVA_HOME"
java -version
javac -version
${{ github.workspace }}/scripts/setup_storefront_env --skip-optional-prompts
${{ github.workspace }}/scripts/setup_storefront_env
pnpm module build
pnpm sample test:android --no-daemon
2 changes: 1 addition & 1 deletion .github/workflows/swift-test-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
env:
STOREFRONT_DOMAIN: example.myshopify.com
STOREFRONT_ACCESS_TOKEN: test-token
run: ${{ github.workspace }}/scripts/setup_storefront_env --skip-optional-prompts
run: ${{ github.workspace }}/scripts/setup_storefront_env

- if: ${{ inputs.setup-storefront-env || inputs.summarize-tests }}
uses: ./.github/actions/setup-mint
Expand Down
4 changes: 2 additions & 2 deletions config/secrets/demo.ejson
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"_public_key": "58b34b9a2be67c206423293ba2c0317e6fbe8f727f7ac124ff62349d36fa0136",
"_description": "Storefront config for the sample apps. Generates .env, run `dev up` to propagate these values to the sample apps.",
"environment": {
"STOREFRONT_DOMAIN": "EJ[1:Vsi9n4WYYvGd935C37cvRzygtUXcpBHu1CkCTFFUqzQ=:MDf5DnXyI+E2j9n1zeMMNprubZ0QpUSS:Ratyqcyc9xd5Ha14St4V0YFjKbt8DhbLK5cOC5GSbGdFyBnHuvtm5mdomVFHqCetPuulRsk=]",
"STOREFRONT_ACCESS_TOKEN": "EJ[1:Vsi9n4WYYvGd935C37cvRzygtUXcpBHu1CkCTFFUqzQ=:31/QaDjKTxu+CgWP1+Pps3/TSphwS16+:oWNA0Zg7iehiUz/kzXPI2sgBV4us6UNEtj2akQTeb3+vF0XRVYSjJfUIa6wqL2Sf]",
"STOREFRONT_DOMAIN": "EJ[1:l7BO8tiknXaR3V2OCydmWpvD6Nsd2/6ZKXWEdXagawo=:afgDjqCHl4uwBnLq0ghL3BAuVs4D2gd+:oyP/5BKL3/TM64sPlmdo5q78zCgKcxzYCqBZWNbCuDjGYPA4vdVfNKVe95dgGhyNYt8=]",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sets the domain for sample app to shared staff store instead of the e2e test store

"STOREFRONT_ACCESS_TOKEN": "EJ[1:l7BO8tiknXaR3V2OCydmWpvD6Nsd2/6ZKXWEdXagawo=:AC4QzxArJXQcTI09aHjNqZfiLF2kkZb2:S5NFZID+ysX9l2/22mgCuxv9GxAbAoEr8VcAGTdHcyEVfeVk5u0awb1/Fl3hkPzP]",
"API_VERSION": "EJ[1:COcqDoNiIoRpNVpn5RtY+/98SiWXneivqVxsvjS2j1M=:tYFS86UJtujPHsIZHB/u4wKb2isFXQFC:/a2Zafq6GTzkympf135XmS+ZHh7L3Zg=]",
"CUSTOMER_ACCOUNT_API_CLIENT_ID": "EJ[1:COcqDoNiIoRpNVpn5RtY+/98SiWXneivqVxsvjS2j1M=:YbjANfMN0CrNMGQ8mHuX7LOSZunMDGl+:KjleSaYcWwtnMkZ3U8WSGNsXq23sOpyD4YYv16WhXhLdyoy3bfe8ShQXE/SOLPdswlo3WA==]",
"CUSTOMER_ACCOUNT_API_SHOP_ID": "EJ[1:COcqDoNiIoRpNVpn5RtY+/98SiWXneivqVxsvjS2j1M=:KjkLuMIgiMHdO1kBj24PTWjmumLq0trf:PFTqWETJCU6Rubg8Zc0+eQT1S5fEBVNDfYOG]",
Expand Down
17 changes: 13 additions & 4 deletions dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,25 @@ up:
met?: ./scripts/secrets_setup --check
meet: "true"
- custom:
name: Copy root env into worktree
name: Copy .env.local, .dev.env, local.properties into worktree
met?: ./scripts/copy_worktree_env --check
meet: ./scripts/copy_worktree_env
- custom:
name: Keep a hand-written .env as .env.local
met?: ./scripts/migrate_env_to_local --check
meet: ./scripts/migrate_env_to_local
- custom:
name: Generate env files from config/secrets
met?: ./scripts/generate_env_files --check
meet: ./scripts/generate_env_files
- custom:
name: Install the pinned Maestro version
met?: ./scripts/install_maestro --check
meet: ./scripts/install_maestro
- custom:
name: Run Checkout Kit workspace setup
met?: ./scripts/setup_dev_workspace --check --skip-optional-prompts
meet: ./scripts/setup_dev_workspace --skip-optional-prompts
met?: ./scripts/setup_dev_workspace --check
meet: ./scripts/setup_dev_workspace
- tophat_mobile
- custom:
name: Configure Tophat Quick Launch items
Expand All @@ -59,6 +67,7 @@ open:

check:
ejson-plaintext: ./scripts/ejson_lint
generate-env-tests: ./scripts/test_generate_env_files
storefront-env-tests: ./scripts/test_setup_storefront_env
ruby-script-tests: ./scripts/test_ruby
maestro-hide-keyboard-lint: ./e2e/scripts/check_hide_keyboard_usage
Expand Down Expand Up @@ -98,7 +107,7 @@ commands:
esac

copy-env:
desc: Copy the root .env into the current worktree so `dev up` can regenerate sample config
desc: Copy .dev.env, .env.local, local.properties into worktree
run: ./scripts/copy_worktree_env

secrets:
Expand Down
2 changes: 1 addition & 1 deletion e2e/scripts/bitrise_ci_helpers
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ e2e_configure_storefront() {
: "${STOREFRONT_DOMAIN:?STOREFRONT_DOMAIN is required. Check https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/workflow_editor#!/secrets and enable Expose for pull requests.}"
: "${STOREFRONT_ACCESS_TOKEN:?STOREFRONT_ACCESS_TOKEN is required. Check https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/workflow_editor#!/secrets and enable Expose for pull requests.}"
e2e_log "Configuring storefront environment"
./scripts/setup_storefront_env --skip-optional-prompts
./scripts/setup_storefront_env
}

e2e_nightly_commit_window() {
Expand Down
25 changes: 6 additions & 19 deletions scripts/copy_worktree_env
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,8 @@

set -euo pipefail

# Copies the repo-root .env (and other root-level machine-local config, if
# present) from the main checkout into the current git worktree, so that a
# subsequent `dev up` can regenerate all nested sample app configuration from it.
#
# Runs automatically as a `dev up` step. With --check it reports (without
# copying) whether the current worktree is missing any root env files: exit 0
# when nothing is needed (main checkout, or already seeded) and non-zero when a
# copy is required, so it can serve as a `dev up` met? probe.
#
# This command prints file paths and status only; it never prints configured
# values.
# Copies gitignored machine-local configuration from the main checkout into the
# current worktree. Generated env files are excluded because `dev up` rebuilds them.

mode="copy"
if [[ "${1:-}" == "--check" ]]; then
Expand All @@ -27,17 +18,15 @@ COMMON_GIT_DIR="$(git rev-parse --path-format=absolute --git-common-dir)"
MAIN_ROOT="$(dirname "${COMMON_GIT_DIR}")"

if [[ "${CURRENT_ROOT}" == "${MAIN_ROOT}" ]]; then
# In the main checkout there is never anything to copy.
[[ "${mode}" == "check" ]] && exit 0
echo "Already in the main checkout (${CURRENT_ROOT}); nothing to copy."
exit 0
fi

# Root-level, gitignored source-of-truth files. Nested sample config
# (Android/Swift/RN) is intentionally omitted: `dev up` regenerates it from the
# root .env via scripts/setup_storefront_env.
# Copying .env would let migrate_env_to_local preserve stale generated values as
# local overrides before this worktree regenerates them.
ROOT_FILES=(
".env"
".env.local"
".dev.env"
"local.properties"
)
Expand All @@ -58,7 +47,6 @@ for rel in "${ROOT_FILES[@]}"; do
continue
fi

# A source file exists in the main checkout but is missing here.
if [[ "${mode}" == "check" ]]; then
echo "missing: ${rel}"
exit 1
Expand All @@ -69,11 +57,10 @@ for rel in "${ROOT_FILES[@]}"; do
copied_any="true"
done

# Check mode reached here with nothing missing: the worktree is already seeded.
[[ "${mode}" == "check" ]] && exit 0

if [[ "${copied_any}" != "true" ]]; then
echo "No new root env files to copy."
echo "No new machine-local files to copy."
fi

echo "Next: run \`dev up\` in this worktree to regenerate sample app config."
128 changes: 128 additions & 0 deletions scripts/generate_env_files
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/env bash

set -euo pipefail

# Generates .env and e2e/.env from committed EJSON secrets. --check reports stale
# output without writing. A missing private key is supported for contributors who
# use their own config; other decrypt failures preserve existing files and fail.

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
KEYDIR="${EJSON_KEYDIR:-/opt/ejson/keys}"

# name:source:destination
PAIRS=(
"demo:config/secrets/demo.ejson:.env"
"e2e:config/secrets/e2e.ejson:e2e/.env"
)

mode="generate"
if [[ "${1:-}" == "--check" ]]; then
mode="check"
elif [[ $# -gt 0 ]]; then
echo "Usage: scripts/generate_env_files [--check]" >&2
exit 1
fi

public_key_of() {
sed -n 's/.*"_public_key"[[:space:]]*:[[:space:]]*"\([0-9a-f]\{64\}\)".*/\1/p' "$1" | head -n 1
}

generated_header() {
local name="$1"
local source_rel="$2"
local dest_rel="$3"

cat <<EOF
# Generated by scripts/generate_env_files from ${source_rel}.
# Do not edit this file: the next \`dev up\` overwrites it.
#
# Shared changes: \`dev secrets edit ${name}\`, then commit ${source_rel}.
EOF

if [[ "${dest_rel}" == ".env" ]]; then
echo "# Gitignored overrides: .env.local."
fi

echo
}

if ! command -v ejson2env >/dev/null 2>&1; then
echo "generate_env_files: ejson2env is not installed, so no env file can be generated." >&2
echo "generate_env_files: run \`dev up\` to install it." >&2
exit 1
fi

stale=()
generated=()
skipped=()

for pair in "${PAIRS[@]}"; do
name="${pair%%:*}"
rest="${pair#*:}"
source_rel="${rest%%:*}"
dest_rel="${rest#*:}"

source_path="${ROOT_DIR}/${source_rel}"
dest_path="${ROOT_DIR}/${dest_rel}"

if [[ ! -f "${source_path}" ]]; then
echo "generate_env_files: ${source_rel} does not exist, so ${dest_rel} is left alone."
skipped+=("${dest_rel}")
continue
fi

public_key="$(public_key_of "${source_path}")"
if [[ -z "${public_key}" ]]; then
echo "generate_env_files: ${source_rel} has no _public_key, so ${dest_rel} cannot be generated." >&2
exit 1
fi

if [[ ! -f "${KEYDIR}/${public_key}" ]]; then
echo "generate_env_files: no private key for ${public_key} in ${KEYDIR}, so ${dest_rel} is left alone."
skipped+=("${dest_rel}")
continue
fi

rendered="$(mktemp)"

if ! {
generated_header "${name}" "${source_rel}" "${dest_rel}"
ejson2env --quiet --keydir "${KEYDIR}" "${source_path}"
} >"${rendered}" 2>/dev/null; then
rm -f "${rendered}"
echo "generate_env_files: could not decrypt ${source_rel}, so ${dest_rel} is unchanged." >&2
echo "generate_env_files: check that the private key for ${public_key} is the current one." >&2
exit 1
fi

if [[ "${mode}" == "check" ]]; then
if [[ ! -f "${dest_path}" ]] || ! cmp -s "${dest_path}" "${rendered}"; then
stale+=("${dest_rel}")
fi

rm -f "${rendered}"
continue
fi

mkdir -p "$(dirname "${dest_path}")"
mv "${rendered}" "${dest_path}"
generated+=("${dest_rel}")
done

if [[ "${mode}" == "check" ]]; then
if [[ "${#stale[@]}" -gt 0 ]]; then
echo "generate_env_files: missing or out of date: ${stale[*]}" >&2
exit 1
fi

echo "generate_env_files: generated env files are up to date."
exit 0
fi

if [[ "${#generated[@]}" -gt 0 ]]; then
echo "generate_env_files: wrote ${generated[*]}"
fi

if [[ "${#skipped[@]}" -gt 0 ]]; then
echo "generate_env_files: your own values in ${skipped[*]} stay under your control."
fi
45 changes: 45 additions & 0 deletions scripts/migrate_env_to_local
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash

set -euo pipefail

# Preserves a hand-written .env as .env.local before .env becomes generated.
# Existing .env.local files are never overwritten.

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

ROOT_ENV="${ROOT_DIR}/.env"
ROOT_ENV_LOCAL="${ROOT_DIR}/.env.local"

mode="migrate"
if [[ "${1:-}" == "--check" ]]; then
mode="check"
elif [[ $# -gt 0 ]]; then
echo "Usage: scripts/migrate_env_to_local [--check]" >&2
exit 1
fi

nothing_to_do() {
[[ "${mode}" == "check" ]] && exit 0

echo "migrate_env_to_local: $1"
exit 0
}

if [[ -e "${ROOT_ENV_LOCAL}" ]]; then
nothing_to_do ".env.local already exists, so nothing is copied."
fi

if [[ ! -f "${ROOT_ENV}" ]]; then
nothing_to_do "no .env to migrate."
fi

if [[ "${mode}" == "check" ]]; then
echo "migrate_env_to_local: .env has no .env.local yet"
exit 1
fi

cp "${ROOT_ENV}" "${ROOT_ENV_LOCAL}"

echo "migrate_env_to_local: copied .env to .env.local, because .env is now generated."
echo "migrate_env_to_local: .env.local wins over .env, so your values keep working."
echo "migrate_env_to_local: delete .env.local to follow the shared config instead."
16 changes: 16 additions & 0 deletions scripts/secrets_edit
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,20 @@ def relative(path)
path.delete_prefix("#{REPO_ROOT}/")
end

# Regenerate after edits under config/secrets. Failure does not discard the
# encrypted edit.
def regenerate_env_files(path)
return unless File.realpath(path).start_with?("#{File.realpath(SECRETS_DIR)}/")

script = File.join(REPO_ROOT, "scripts", "generate_env_files")
out, status = Open3.capture2e(script)
print out

return if status.success?

warn CliOutput.suggestion("the edit is saved; rerun `dev up` once that is fixed")
end

subcommand, target, *extra = ARGV

if ["--help", "-h", "help"].include?(subcommand)
Expand Down Expand Up @@ -184,4 +198,6 @@ Dir.mktmpdir("secrets-edit") do |workspace|
puts "Updated #{relative(path)}. #{changed.length} value(s) changed:"
changed.each { |key| puts " #{key}" }
puts "Commit the file to share the change."

regenerate_env_files(path)
end
Loading
Loading