Skip to content

Commit ba0a340

Browse files
committed
RUM-11897: Add scripts to set/get Vault secrets & Migrate CI
1 parent ed7f4e1 commit ba0a340

File tree

6 files changed

+335
-38
lines changed

6 files changed

+335
-38
lines changed

ci/pipelines/default-pipeline.yml

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ include:
44
# SETUP
55

66
stages:
7+
- fetch-secrets
78
- ci-image
89
- security
910
- analysis
@@ -13,6 +14,10 @@ stages:
1314
- notify
1415

1516
.snippets:
17+
fetch-secrets:
18+
- mkdir -p ./ci/pipelines/secrets
19+
- ./ci/scripts/fetch-secrets.sh
20+
1621
# macOS AMI will already have cmdline-tools installed
1722
install-android-api-components:
1823
- echo y | ~/android_sdk/cmdline-tools/latest/bin/sdkmanager --install "emulator"
@@ -39,15 +44,27 @@ stages:
3944
- if [[ "$exit_code" -ne 0 ]]; then exit 1; fi
4045
- exit 0
4146
set-publishing-credentials:
42-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.gradle-properties --with-decryption --query "Parameter.Value" --out text >> ./gradle.properties
43-
- export GPG_PRIVATE_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.signing.gpg_private_key --with-decryption --query "Parameter.Value" --out text)
44-
- export GPG_PASSWORD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.signing.gpg_passphrase --with-decryption --query "Parameter.Value" --out text)
45-
- export CENTRAL_PUBLISHER_USERNAME=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.publishing.central_username --with-decryption --query "Parameter.Value" --out text)
46-
- export CENTRAL_PUBLISHER_PASSWORD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.publishing.central_password --with-decryption --query "Parameter.Value" --out text)
47-
- export GPG_PUBLIC_FINGERPRINT=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.signing.gpg_public_key --with-decryption --query "Parameter.Value" --out text | gpg --import --import-options show-only | grep -E -o -e "[A-F0-9]{40}")
47+
- cp ./ci/pipelines/secrets/gradle.properties ./gradle.properties
48+
- export GPG_PRIVATE_KEY=$(cat ./ci/pipelines/secrets/gpg_private_key)
49+
- export GPG_PASSWORD=$(cat ./ci/pipelines/secrets/gpg_passphrase)
50+
- export CENTRAL_PUBLISHER_USERNAME=$(cat ./ci/pipelines/secrets/central_username)
51+
- export CENTRAL_PUBLISHER_PASSWORD=$(cat ./ci/pipelines/secrets/central_password)
52+
- export GPG_PUBLIC_FINGERPRINT=$(cat ./ci/pipelines/secrets/gpg_public_key | gpg --import --import-options show-only | grep -E -o -e "[A-F0-9]{40}")
4853

4954
# CI IMAGE
5055

56+
fetch-secrets:
57+
stage: fetch-secrets
58+
tags: ["macos:sonoma","specific:true"]
59+
image: $CI_IMAGE_DOCKER
60+
script:
61+
- !reference [.snippets, fetch-secrets]
62+
artifacts:
63+
paths:
64+
- ./ci/pipelines/secrets/
65+
expire_in: 1 hour
66+
when: always
67+
5168
ci-image:
5269
stage: ci-image
5370
when: manual
@@ -185,9 +202,9 @@ test:kover:
185202
- pip3 install datadog
186203
- rm -rf ~/.gradle/daemon/
187204
- export DD_AGENT_HOST="$BUILDENV_HOST_IP"
188-
- export DD_API_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.api_key --with-decryption --query "Parameter.Value" --out text)
189-
- export DD_APP_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.app_key --with-decryption --query "Parameter.Value" --out text)
190-
- CODECOV_TOKEN=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.codecov-token --with-decryption --query "Parameter.Value" --out text)
205+
- export DD_API_KEY=$(cat ./ci/pipelines/secrets/api_key)
206+
- export DD_APP_KEY=$(cat ./ci/pipelines/secrets/app_key)
207+
- CODECOV_TOKEN=$(cat ./ci/pipelines/secrets/codecov_token)
191208
- GRADLE_OPTS="-Xmx3072m" DD_TAGS="test.configuration.variant:release" ./gradlew :dd-sdk-android-core:koverXmlReportRelease --no-daemon --build-cache --gradle-user-home cache/ -Dorg.gradle.jvmargs=-javaagent:$DD_TRACER_FOLDER/dd-java-agent.jar=$DD_COMMON_AGENT_CONFIG
192209
- GRADLE_OPTS="-Xmx3072m" DD_TAGS="test.configuration.variant:release" ./gradlew :dd-sdk-android-internal:koverXmlReportRelease --no-daemon --build-cache --gradle-user-home cache/ -Dorg.gradle.jvmargs=-javaagent:$DD_TRACER_FOLDER/dd-java-agent.jar=$DD_COMMON_AGENT_CONFIG
193210
- GRADLE_OPTS="-Xmx3072m" DD_TAGS="test.configuration.variant:release" ./gradlew :koverReportFeatures --no-daemon --build-cache --gradle-user-home cache/ -Dorg.gradle.jvmargs=-javaagent:$DD_TRACER_FOLDER/dd-java-agent.jar=$DD_COMMON_AGENT_CONFIG
@@ -373,7 +390,7 @@ test-pyramid:detekt-api-coverage:
373390
timeout: 1h
374391
script:
375392
- mkdir -p ./config/
376-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.gradle-properties --with-decryption --query "Parameter.Value" --out text >> ./gradle.properties
393+
- cp ./ci/pipelines/secrets/gradle.properties ./gradle.properties
377394
- GRADLE_OPTS="-Xmx4096M" ./gradlew assembleLibrariesDebug --stacktrace --no-daemon
378395
- GRADLE_OPTS="-Xmx4096M" ./gradlew printSdkDebugRuntimeClasspath --stacktrace --no-daemon
379396
- GRADLE_OPTS="-Xmx4096M" ./gradlew :tools:detekt:jar --stacktrace --no-daemon
@@ -391,13 +408,13 @@ test-pyramid:publish-e2e-synthetics:
391408
- develop
392409
script:
393410
- mkdir -p ./config/
394-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.gradle-properties --with-decryption --query "Parameter.Value" --out text >> ./gradle.properties
395-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore --with-decryption --query "Parameter.Value" --out text | base64 -d > ./sample-android.keystore
396-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_config_json --with-decryption --query "Parameter.Value" --out text > ./config/us1.json
397-
- export E2E_STORE_PASSWD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore-password --with-decryption --query "Parameter.Value" --out text)
398-
- export E2E_DD_API_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_api_key --with-decryption --query "Parameter.Value" --out text)
399-
- export E2E_DD_APP_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_app_key --with-decryption --query "Parameter.Value" --out text)
400-
- export E2E_MOBILE_APP_ID=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_mobile_app_id --with-decryption --query "Parameter.Value" --out text)
411+
- cp ./ci/pipelines/secrets/gradle.properties ./gradle.properties
412+
- cp ./ci/pipelines/secrets/keystore ./sample-android.keystore
413+
- cp ./ci/pipelines/secrets/e2e_config.json ./config/us1.json
414+
- export E2E_STORE_PASSWD=$(cat ./ci/pipelines/secrets/keystore_password)
415+
- export E2E_DD_API_KEY=$(cat ./ci/pipelines/secrets/e2e_api_key)
416+
- export E2E_DD_APP_KEY=$(cat ./ci/pipelines/secrets/e2e_app_key)
417+
- export E2E_MOBILE_APP_ID=$(cat ./ci/pipelines/secrets/e2e_mobile_app_id)
401418
- GRADLE_OPTS="-Xmx4096M" ./gradlew assembleLibrariesRelease --stacktrace --no-daemon
402419
- GRADLE_OPTS="-Xmx4096M" ./gradlew :sample:kotlin:packageUs1Release --stacktrace --no-daemon
403420
- npm update -g @datadog/datadog-ci
@@ -418,13 +435,13 @@ test-pyramid:publish-webview-synthetics:
418435
- develop
419436
script:
420437
- mkdir -p ./config/
421-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.gradle-properties --with-decryption --query "Parameter.Value" --out text >> ./gradle.properties
422-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore --with-decryption --query "Parameter.Value" --out text | base64 -d > ./sample-android.keystore
423-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.webview_config_json --with-decryption --query "Parameter.Value" --out text > ./config/us1.json
424-
- export E2E_STORE_PASSWD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore-password --with-decryption --query "Parameter.Value" --out text)
425-
- export E2E_DD_API_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.webview_api_key --with-decryption --query "Parameter.Value" --out text)
426-
- export E2E_DD_APP_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.webview_app_key --with-decryption --query "Parameter.Value" --out text)
427-
- export E2E_MOBILE_APP_ID=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.webview_mobile_app_id --with-decryption --query "Parameter.Value" --out text)
438+
- cp ./ci/pipelines/secrets/gradle.properties ./gradle.properties
439+
- cp ./ci/pipelines/secrets/keystore ./sample-android.keystore
440+
- cp ./ci/pipelines/secrets/webview_config.json ./config/us1.json
441+
- export E2E_STORE_PASSWD=$(cat ./ci/pipelines/secrets/keystore_password)
442+
- export E2E_DD_API_KEY=$(cat ./ci/pipelines/secrets/webview_api_key)
443+
- export E2E_DD_APP_KEY=$(cat ./ci/pipelines/secrets/webview_app_key)
444+
- export E2E_MOBILE_APP_ID=$(cat ./ci/pipelines/secrets/webview_mobile_app_id)
428445
- GRADLE_OPTS="-Xmx4096M" ./gradlew assembleLibrariesRelease --stacktrace --no-daemon
429446
- GRADLE_OPTS="-Xmx4096M" ./gradlew :sample:kotlin:packageUs1Release --stacktrace --no-daemon
430447
- npm update -g @datadog/datadog-ci
@@ -445,13 +462,13 @@ test-pyramid:publish-staging-synthetics:
445462
- develop
446463
script:
447464
- mkdir -p ./config/
448-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.gradle-properties --with-decryption --query "Parameter.Value" --out text >> ./gradle.properties
449-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore --with-decryption --query "Parameter.Value" --out text | base64 -d > ./sample-android.keystore
450-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_staging_config_json --with-decryption --query "Parameter.Value" --out text > ./config/staging.json
451-
- export E2E_STORE_PASSWD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore-password --with-decryption --query "Parameter.Value" --out text)
452-
- export E2E_DD_API_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_staging_api_key --with-decryption --query "Parameter.Value" --out text)
453-
- export E2E_DD_APP_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_staging_app_key --with-decryption --query "Parameter.Value" --out text)
454-
- export E2E_MOBILE_APP_ID=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.e2e_staging_mobile_app_id --with-decryption --query "Parameter.Value" --out text)
465+
- cp ./ci/pipelines/secrets/gradle.properties ./gradle.properties
466+
- cp ./ci/pipelines/secrets/keystore ./sample-android.keystore
467+
- cp ./ci/pipelines/secrets/e2e_staging_config.json ./config/staging.json
468+
- export E2E_STORE_PASSWD=$(cat ./ci/pipelines/secrets/keystore_password)
469+
- export E2E_DD_API_KEY=$(cat ./ci/pipelines/secrets/e2e_staging_api_key)
470+
- export E2E_DD_APP_KEY=$(cat ./ci/pipelines/secrets/e2e_staging_app_key)
471+
- export E2E_MOBILE_APP_ID=$(cat ./ci/pipelines/secrets/e2e_staging_app_id)
455472
- GRADLE_OPTS="-Xmx4096M" ./gradlew assembleLibrariesRelease --stacktrace --no-daemon
456473
- GRADLE_OPTS="-Xmx4096M" ./gradlew :sample:kotlin:packageStagingRelease --stacktrace --no-daemon
457474
- npm update -g @datadog/datadog-ci
@@ -472,13 +489,13 @@ test-pyramid:publish-benchmark-synthetics:
472489
- develop
473490
script:
474491
- mkdir -p ./config/
475-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.gradle-properties --with-decryption --query "Parameter.Value" --out text >> ./gradle.properties
476-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore --with-decryption --query "Parameter.Value" --out text | base64 -d > ./sample-benchmark.keystore
477-
- aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.benchmark_config_json --with-decryption --query "Parameter.Value" --out text > ./config/benchmark.json
478-
- export BM_STORE_PASSWD=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.keystore-password --with-decryption --query "Parameter.Value" --out text)
479-
- export BM_DD_API_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.benchmark_api_key --with-decryption --query "Parameter.Value" --out text)
480-
- export BM_DD_APP_KEY=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.benchmark_app_key --with-decryption --query "Parameter.Value" --out text)
481-
- export BM_MOBILE_APP_ID=$(aws ssm get-parameter --region us-east-1 --name ci.dd-sdk-android.benchmark_mobile_app_id --with-decryption --query "Parameter.Value" --out text)
492+
- cp ./ci/pipelines/secrets/gradle.properties ./gradle.properties
493+
- cp ./ci/pipelines/secrets/keystore ./sample-benchmark.keystore
494+
- cp ./ci/pipelines/secrets/benchmark_config.json ./config/benchmark.json
495+
- export BM_STORE_PASSWD=$(cat ./ci/pipelines/secrets/keystore_password)
496+
- export BM_DD_API_KEY=$(cat ./ci/pipelines/secrets/benchmark_api_key)
497+
- export BM_DD_APP_KEY=$(cat ./ci/pipelines/secrets/benchmark_app_key)
498+
- export BM_MOBILE_APP_ID=$(cat ./ci/pipelines/secrets/benchmark_mobile_app_id)
482499
- GRADLE_OPTS="-Xmx4096M" ./gradlew assembleLibrariesRelease --stacktrace --no-daemon
483500
- GRADLE_OPTS="-Xmx4096M" ./gradlew :sample:benchmark:packageRelease --stacktrace --no-daemon
484501
- npm update -g @datadog/datadog-ci

ci/scripts/fetch-secrets.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#
2+
# Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
# This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
# Copyright 2016-Present Datadog, Inc.
5+
#
6+
7+
source ./ci/scripts/vault_config.sh
8+
source ./ci/scripts/get-secret.sh
9+
10+
# Gradle properties
11+
get_secret $DD_ANDROID_SECRET__GRADLE_PROPERTIES > ./ci/pipelines/secrets/gradle.properties
12+
# Signing and publishing
13+
get_secret $DD_ANDROID_SECRET__SIGNING_GPG_PRIVATE_KEY > ./ci/pipelines/secrets/gpg_private_key
14+
get_secret $DD_ANDROID_SECRET__SIGNING_GPG_PASSPHRASE > ./ci/pipelines/secrets/gpg_passphrase
15+
get_secret $DD_ANDROID_SECRET__SIGNING_GPG_PUBLIC_KEY > ./ci/pipelines/secrets/gpg_public_key
16+
get_secret $DD_ANDROID_SECRET__PUBLISHING_CENTRAL_USERNAME > ./ci/pipelines/secrets/central_username
17+
get_secret $DD_ANDROID_SECRET__PUBLISHING_CENTRAL_PWD > ./ci/pipelines/secrets/central_password
18+
# API and App keys
19+
get_secret $DD_ANDROID_SECRET__API_KEY > ./ci/pipelines/secrets/api_key
20+
get_secret $DD_ANDROID_SECRET__APP_KEY > ./ci/pipelines/secrets/app_key
21+
get_secret $DD_ANDROID_SECRET__CODECOV_TOKEN > ./ci/pipelines/secrets/codecov_token
22+
# Keystore
23+
get_secret $DD_ANDROID_SECRET__KEYSTORE > ./ci/pipelines/secrets/keystore
24+
get_secret $DD_ANDROID_SECRET__KEYSTORE_PWD > ./ci/pipelines/secrets/keystore_password
25+
# E2E Testing
26+
get_secret $DD_ANDROID_SECRET__E2E_CONFIG_JSON > ./ci/pipelines/secrets/e2e_config.json
27+
get_secret $DD_ANDROID_SECRET__E2E_API_KEY > ./ci/pipelines/secrets/e2e_api_key
28+
get_secret $DD_ANDROID_SECRET__E2E_APP_KEY > ./ci/pipelines/secrets/e2e_app_key
29+
get_secret $DD_ANDROID_SECRET__E2E_MOBILE_APP_ID > ./ci/pipelines/secrets/e2e_mobile_app_id
30+
# WebView
31+
get_secret $DD_ANDROID_SECRET__WEBVIEW_CONFIG_JSON > ./ci/pipelines/secrets/webview_config.json
32+
get_secret $DD_ANDROID_SECRET__WEBVIEW_API_KEY > ./ci/pipelines/secrets/webview_api_key
33+
get_secret $DD_ANDROID_SECRET__WEBVIEW_APP_KEY > ./ci/pipelines/secrets/webview_app_key
34+
get_secret $DD_ANDROID_SECRET__WEBVIEW_MOBILE_APP_ID > ./ci/pipelines/secrets/webview_mobile_app_id
35+
# Staging
36+
get_secret $DD_ANDROID_SECRET__E2E_STAGING_CONFIG_JSON > ./ci/pipelines/secrets/e2e_staging_config.json
37+
get_secret $DD_ANDROID_SECRET__E2E_STAGING_API_KEY > ./ci/pipelines/secrets/e2e_staging_api_key
38+
get_secret $DD_ANDROID_SECRET__E2E_STAGING_APP_KEY > ./ci/pipelines/secrets/e2e_staging_app_key
39+
get_secret $DD_ANDROID_SECRET__E2E_STAGING_APP_ID > ./ci/pipelines/secrets/e2e_staging_app_id
40+
# Benchmark
41+
get_secret $DD_ANDROID_SECRET__BENCHMARK_CONFIG_JSON > ./ci/pipelines/secrets/benchmark_config.json
42+
get_secret $DD_ANDROID_SECRET__BENCHMARK_API_KEY > ./ci/pipelines/secrets/benchmark_api_key
43+
get_secret $DD_ANDROID_SECRET__BENCHMARK_APP_KEY > ./ci/pipelines/secrets/benchmark_app_key
44+
get_secret $DD_ANDROID_SECRET__BENCHMARK_MOBILE_APP_ID > ./ci/pipelines/secrets/benchmark_mobile_app_id

ci/scripts/get-secret.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/zsh
2+
3+
#
4+
# Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
5+
# This product includes software developed at Datadog (https://www.datadoghq.com/).
6+
# Copyright 2016-Present Datadog, Inc.
7+
#
8+
9+
source ./ci/scripts/vault_config.sh
10+
source ./ci/scripts/list-secrets.sh
11+
12+
# Usage:
13+
# get_secret <secret_name>
14+
#
15+
# Notes:
16+
# - For <secret_name> use constants defined in './ci/scripts/vault_config.sh'
17+
# - Requires `vault` to be installed
18+
get_secret() {
19+
local secret_name=$1
20+
21+
export VAULT_ADDR=$DD_VAULT_ADDR
22+
23+
if [ "$CI" = "true" ]; then
24+
echo "Login as CI"
25+
vault login -method=aws -no-print
26+
else
27+
if vault token lookup &>/dev/null; then
28+
echo "Reading '$secret_name' secret in local env. You are already authenticated with 'vault'." >&2
29+
else
30+
echo "Reading '$secret_name' secret in local env. You will now be authenticated with OIDC in your web browser." >&2
31+
vault login -method=oidc -no-print
32+
fi
33+
fi
34+
35+
local secret_value=$(vault kv get -field=value "$DD_ANDROID_SECRETS_PATH_PREFIX/$secret_name")
36+
37+
if [[ -z "$secret_value" ]]; then
38+
echo "Error" "Failed to retrieve the '$secret_name' secret or the secret is empty." >&2
39+
exit 1
40+
fi
41+
42+
echo "$secret_value"
43+
}
44+
45+
# Only run the main logic if the script is executed directly (not sourced)
46+
if [ "$CI" != "true" ]; then
47+
list_secrets
48+
select_secret
49+
get_secret "$SECRET_NAME"
50+
fi

ci/scripts/list-secrets.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/zsh
2+
3+
#
4+
# Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
5+
# This product includes software developed at Datadog (https://www.datadoghq.com/).
6+
# Copyright 2016-Present Datadog, Inc.
7+
#
8+
9+
source ./ci/scripts/vault_config.sh
10+
11+
list_secrets() {
12+
GREEN="\e[32m"
13+
RESET="\e[0m"
14+
15+
echo "Available secrets:"
16+
for key in ${(k)DD_ANDROID_SECRETS}; do
17+
IFS=" | " read -r name description <<< "${DD_ANDROID_SECRETS[$key]}"
18+
echo "$key) ${GREEN}$name${RESET} - $description"
19+
done | sort -n
20+
21+
echo ""
22+
echo "To add a new secret, first define it in 'tools/secrets/config.sh' and retry."
23+
}
24+
25+
26+
select_secret() {
27+
echo
28+
while true; do
29+
echo "Enter the number of the secret you want to continue:"
30+
read "secret_number"
31+
if [[ -n ${DD_ANDROID_SECRETS[$secret_number]} ]]; then
32+
IFS=" | " read -r SECRET_NAME SECRET_DESC <<< "${DD_ANDROID_SECRETS[$secret_number]}"
33+
break
34+
else
35+
echo_err "Invalid selection. Please enter a valid number."
36+
fi
37+
done
38+
}

0 commit comments

Comments
 (0)