Skip to content

Commit 81af29d

Browse files
atergaclaude
andauthored
chore: fixes and improvements for the release process (dfinity#3703)
## Summary Follow-up fixes to the release SOP script (merged in dfinity#3699): - **Fall back to `.ic0.app`** when `.icp0.io` config endpoint is unavailable - **Split `prepare_proposal_argument`** into per-canister steps for finer-grained checklist progress - **Fix Candid parsing**: handle multi-line nested values (analytics_config, related_origins) - **Default missing fields to `null`**: prevents `dev_csp = ` causing didc encode failures - **Fix backend init arg**: default to `(null)` when user declines optional value - **Idempotent `append_proposal_argument`**: removes previously appended sections on re-run, adds Wasm Verification section - **Use HTTPS for git operations**: avoids SSH key prompts for public operations - **Format Candid args**: one top-level field per line for readability ## Test plan - [ ] Run `./scripts/make-upgrade-proposal --new --name release-test` and verify the improved flow - [ ] Run `./scripts/deploy-pr-to-beta -sa -fe <PR>` and verify shared helpers work correctly | [Next PR](dfinity#3702) > --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d036ad3 commit 81af29d

2 files changed

Lines changed: 152 additions & 61 deletions

File tree

scripts/frontend-arg-helpers.bash

Lines changed: 78 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,21 @@ prompt_field() {
3131
# -------------------------
3232
build_frontend_install_arg() {
3333
local canister_id="$1"
34-
local config_url="https://${canister_id}.icp0.io/.config"
34+
local primary_url="https://${canister_id}.icp0.io/.config"
35+
local fallback_url="https://${canister_id}.ic0.app/.config"
3536

3637
echo ""
37-
echo "Fetching current frontend config from $config_url ..."
38-
local raw_config
39-
if ! raw_config=$(curl --connect-timeout 10 --max-time 30 -sfL "$config_url"); then
40-
echo "Error: Could not fetch current config from $config_url" >&2
41-
exit 1
42-
fi
38+
local raw_config=""
39+
for config_url in "$primary_url" "$fallback_url"; do
40+
echo "Fetching current frontend config from $config_url ..."
41+
if raw_config=$(curl --connect-timeout 10 --max-time 30 -sfL "$config_url") && [ -n "$raw_config" ]; then
42+
break
43+
fi
44+
echo " Failed, trying next domain..." >&2
45+
raw_config=""
46+
done
4347
if [ -z "$raw_config" ]; then
44-
echo "Error: Empty config response from $config_url" >&2
48+
echo "Error: Could not fetch config from either $primary_url or $fallback_url" >&2
4549
exit 1
4650
fi
4751

@@ -52,37 +56,81 @@ build_frontend_install_arg() {
5256
echo "Configure install arguments (press Enter to keep each current value):"
5357

5458
# Parse individual fields from the Candid text output.
59+
# For multi-line nested values (analytics_config, related_origins), we extract
60+
# everything from "field = " to the matching closing brace/semicolon.
61+
parse_candid_field() {
62+
local field="$1" config="$2"
63+
# Try multi-line extraction: from "field = " to the line where braces balance
64+
awk -v field="$field" '
65+
BEGIN { found=0; depth=0; val="" }
66+
!found && $0 ~ field" = " {
67+
found=1
68+
sub(".*"field" = ", "")
69+
# Remove trailing semicolon if this is a single-line value
70+
}
71+
found {
72+
val = (val == "" ? $0 : val "\n" $0)
73+
depth += gsub(/[{(]/, "&")
74+
depth -= gsub(/[})]/, "&")
75+
if (depth <= 0) {
76+
# Remove trailing semicolon at the top level
77+
sub(/;[[:space:]]*$/, "", val)
78+
print val
79+
exit
80+
}
81+
}
82+
' <<< "$config"
83+
}
84+
5585
local current_backend_canister_id
56-
current_backend_canister_id=$(echo "$raw_config" | grep 'backend_canister_id' | sed 's/.*= *//;s/ *;$//')
86+
current_backend_canister_id=$(parse_candid_field "backend_canister_id" "$raw_config")
5787
local current_backend_origin
58-
current_backend_origin=$(echo "$raw_config" | grep 'backend_origin' | sed 's/.*= *//;s/ *;$//')
88+
current_backend_origin=$(parse_candid_field "backend_origin" "$raw_config")
5989
local current_related_origins
60-
current_related_origins=$(echo "$raw_config" | sed -n '/related_origins/,/}/p' | tr '\n' ' ' | sed 's/.*= *//;s/ *;[[:space:]]*$//')
90+
current_related_origins=$(parse_candid_field "related_origins" "$raw_config")
6191
local current_fetch_root_key
62-
current_fetch_root_key=$(echo "$raw_config" | grep 'fetch_root_key' | sed 's/.*= *//;s/ *;$//')
92+
current_fetch_root_key=$(parse_candid_field "fetch_root_key" "$raw_config")
6393
local current_analytics_config
64-
current_analytics_config=$(echo "$raw_config" | grep 'analytics_config' | sed 's/.*= *//;s/ *;$//')
94+
current_analytics_config=$(parse_candid_field "analytics_config" "$raw_config")
6595
local current_dummy_auth
66-
current_dummy_auth=$(echo "$raw_config" | grep 'dummy_auth' | sed 's/.*= *//;s/ *;$//')
96+
current_dummy_auth=$(parse_candid_field "dummy_auth" "$raw_config")
6797
local current_dev_csp
68-
current_dev_csp=$(echo "$raw_config" | grep 'dev_csp' | sed 's/.*= *//;s/ *;$//')
98+
current_dev_csp=$(parse_candid_field "dev_csp" "$raw_config")
99+
100+
# All known fields with their defaults (null for missing fields)
101+
local -a field_names=(backend_canister_id backend_origin related_origins fetch_root_key analytics_config dummy_auth dev_csp)
102+
local -A current_values=(
103+
[backend_canister_id]="$current_backend_canister_id"
104+
[backend_origin]="$current_backend_origin"
105+
[related_origins]="$current_related_origins"
106+
[fetch_root_key]="$current_fetch_root_key"
107+
[analytics_config]="$current_analytics_config"
108+
[dummy_auth]="$current_dummy_auth"
109+
[dev_csp]="$current_dev_csp"
110+
)
111+
112+
# Prompt for each field, defaulting empty values to null
113+
local -A final_values
114+
for field in "${field_names[@]}"; do
115+
local current="${current_values[$field]:-null}"
116+
local value
117+
value=$(prompt_field "$field" "$current")
118+
# Normalize empty input to null to avoid invalid Candid
119+
final_values[$field]="${value:-null}"
120+
done
69121

70-
local val_backend_canister_id
71-
val_backend_canister_id=$(prompt_field "backend_canister_id" "$current_backend_canister_id")
72-
local val_backend_origin
73-
val_backend_origin=$(prompt_field "backend_origin" "$current_backend_origin")
74-
local val_related_origins
75-
val_related_origins=$(prompt_field "related_origins" "$current_related_origins")
76-
local val_fetch_root_key
77-
val_fetch_root_key=$(prompt_field "fetch_root_key" "$current_fetch_root_key")
78-
local val_analytics_config
79-
val_analytics_config=$(prompt_field "analytics_config" "$current_analytics_config")
80-
local val_dummy_auth
81-
val_dummy_auth=$(prompt_field "dummy_auth" "$current_dummy_auth")
82-
local val_dev_csp
83-
val_dev_csp=$(prompt_field "dev_csp" "$current_dev_csp")
122+
# Build the Candid record with each top-level field on its own line
123+
local record_fields=""
124+
for field in "${field_names[@]}"; do
125+
if [ -n "$record_fields" ]; then
126+
record_fields+=$';\n'
127+
fi
128+
record_fields+=" ${field} = ${final_values[$field]}"
129+
done
84130

85-
FRONTEND_CANDID_ARG="(record { backend_canister_id = ${val_backend_canister_id}; backend_origin = ${val_backend_origin}; related_origins = ${val_related_origins}; fetch_root_key = ${val_fetch_root_key}; analytics_config = ${val_analytics_config}; dummy_auth = ${val_dummy_auth}; dev_csp = ${val_dev_csp} })"
131+
FRONTEND_CANDID_ARG="(record {
132+
${record_fields};
133+
})"
86134

87135
echo ""
88136
echo "Install argument (Candid):"

scripts/make-upgrade-proposal

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ set -euo pipefail
1010
SOURCE_DIR="$(dirname "${BASH_SOURCE[0]}")"
1111
source "$SOURCE_DIR/frontend-arg-helpers.bash"
1212

13+
# Resolve the HTTPS remote URL for git operations that don't need SSH.
14+
# gh is authenticated via HTTPS, so this avoids SSH key prompts for
15+
# public read operations (fetch) and authenticated writes (push).
16+
REPO_HTTPS_URL="https://github.com/dfinity/internet-identity.git"
17+
1318
print_help() {
1419
cat <<-EOF
1520
@@ -365,6 +370,9 @@ prepare_staging_backend_argument() {
365370
echo "=== Filling init arguments for STAGING BACKEND canister (InternetIdentityInit) ==="
366371
echo ""
367372
didc_assist_ii_init > staging_args.txt
373+
if [ ! -s staging_args.txt ]; then
374+
echo "(null)" > staging_args.txt
375+
fi
368376
didc_encode_ii_init staging_args.txt > staging_dfx_arg.bin
369377
}
370378

@@ -494,40 +502,56 @@ compute_sha256sum_for_frontend_args() {
494502
didc_encode_frontend_init "$ARG_FILE" | xxd -r -p | sha256sum | cut -f1 -d' '
495503
}
496504

497-
prepare_proposal_argument() {
498-
local upgrade_type="$(checklist_must_get 'Upgrade type')"
505+
prepare_production_backend_argument() {
499506
echo "You need at least the didc from 2024-07-29 https://github.com/dfinity/candid/releases/tag/2024-07-29"
500-
501-
if should_upgrade_backend "$upgrade_type"; then
502-
echo ""
503-
echo "=== Filling init arguments for PRODUCTION BACKEND canister (InternetIdentityInit) ==="
504-
echo ""
505-
didc_assist_ii_init > args.txt
506-
didc_encode_ii_init args.txt > dfx_arg.bin
507-
# DFX raw arguments are encoded differently than ic-admin's --arg values (mainnet_arg.bin).
508-
xxd -r -p dfx_arg.bin > mainnet_arg.bin
507+
echo ""
508+
echo "=== Filling init arguments for PRODUCTION BACKEND canister (InternetIdentityInit) ==="
509+
echo ""
510+
didc_assist_ii_init > args.txt
511+
# Default to (null) when the user declines the optional init arg
512+
if [ ! -s args.txt ]; then
513+
echo "(null)" > args.txt
509514
fi
515+
didc_encode_ii_init args.txt > dfx_arg.bin
516+
# DFX raw arguments are encoded differently than ic-admin's --arg values (mainnet_arg.bin).
517+
xxd -r -p dfx_arg.bin > mainnet_arg.bin
518+
}
510519

511-
if should_upgrade_frontend "$upgrade_type"; then
512-
echo ""
513-
echo "=== Filling init arguments for PRODUCTION FRONTEND canister ==="
514-
echo ""
515-
build_frontend_install_arg "$PROD_FRONTEND_CANISTER_ID"
516-
echo "$FRONTEND_CANDID_ARG" > frontend_args.txt
517-
echo "$FRONTEND_INSTALL_ARG" > dfx_frontend_arg.bin
518-
xxd -r -p dfx_frontend_arg.bin > mainnet_frontend_arg.bin
519-
fi
520+
prepare_production_frontend_argument() {
521+
echo ""
522+
echo "=== Filling init arguments for PRODUCTION FRONTEND canister ==="
523+
echo ""
524+
build_frontend_install_arg "$PROD_FRONTEND_CANISTER_ID"
525+
echo "$FRONTEND_CANDID_ARG" > frontend_args.txt
526+
echo "$FRONTEND_INSTALL_ARG" > dfx_frontend_arg.bin
527+
xxd -r -p dfx_frontend_arg.bin > mainnet_frontend_arg.bin
520528
}
521529

522530
append_proposal_argument() {
523531
local upgrade_type="$(checklist_must_get 'Upgrade type')"
524-
532+
local git_commit
533+
git_commit=$(git rev-parse "$TAG_NAME")
534+
525535
if should_upgrade_backend "$upgrade_type"; then
526-
# Get the arguments from the file
527536
ARGUMENTS="$(cat args.txt)"
528-
537+
II_WASM_SHA=$(sha256sum "internet_identity.wasm.gz" | awk '{print $1}')
538+
539+
# Remove previously appended sections (idempotent on re-run)
540+
sed -i.bak '/^## Backend Argument Verification/,$d' backend_proposal.md && rm -f backend_proposal.md.bak
541+
sed -i.bak '/^## Wasm Verification/,$d' backend_proposal.md && rm -f backend_proposal.md.bak
542+
529543
cat >> backend_proposal.md << EOF
530544
545+
## Wasm Verification
546+
547+
To build the wasm modules yourself and verify their hashes, run the following commands from the root of the [Internet Identity repository](https://github.com/dfinity/internet-identity):
548+
549+
\`\`\`
550+
git pull # to ensure you have the latest changes.
551+
git checkout ${git_commit}
552+
./scripts/verify-hash --ii-hash ${II_WASM_SHA}
553+
\`\`\`
554+
531555
## Backend Argument Verification
532556
533557
Run the following command to verify the backend upgrade argument hash:
@@ -539,13 +563,27 @@ didc encode -d ./src/internet_identity/internet_identity.did -t '(opt InternetId
539563
The output should match the argument hash.
540564
EOF
541565
fi
542-
566+
543567
if should_upgrade_frontend "$upgrade_type"; then
544-
# Get the frontend arguments from the file
545568
FRONTEND_ARGUMENTS="$(cat frontend_args.txt)"
546-
569+
FRONTEND_WASM_SHA=$(sha256sum "internet_identity_frontend.wasm.gz" | awk '{print $1}')
570+
571+
# Remove previously appended sections (idempotent on re-run)
572+
sed -i.bak '/^## Frontend Argument Verification/,$d' frontend_proposal.md && rm -f frontend_proposal.md.bak
573+
sed -i.bak '/^## Wasm Verification/,$d' frontend_proposal.md && rm -f frontend_proposal.md.bak
574+
547575
cat >> frontend_proposal.md << EOF
548576
577+
## Wasm Verification
578+
579+
To build the wasm modules yourself and verify their hashes, run the following commands from the root of the [Internet Identity repository](https://github.com/dfinity/internet-identity):
580+
581+
\`\`\`
582+
git pull # to ensure you have the latest changes.
583+
git checkout ${git_commit}
584+
./scripts/verify-hash --iife-hash ${FRONTEND_WASM_SHA}
585+
\`\`\`
586+
549587
## Frontend Argument Verification
550588
551589
Run the following command to verify the frontend upgrade argument hash:
@@ -746,15 +784,15 @@ tag_proposal() {
746784
backend_proposal_num=$(checklist_get "Backend proposal number")
747785
if [ "$backend_proposal_num" ]; then
748786
git tag -f "proposal-backend-$backend_proposal_num"
749-
git push origin "proposal-backend-$backend_proposal_num"
787+
git push "$REPO_HTTPS_URL" "proposal-backend-$backend_proposal_num"
750788
fi
751789
fi
752790

753791
if should_upgrade_frontend "$upgrade_type"; then
754792
frontend_proposal_num=$(checklist_get "Frontend proposal number")
755793
if [ "$frontend_proposal_num" ]; then
756794
git tag -f "proposal-frontend-$frontend_proposal_num"
757-
git push origin "proposal-frontend-$frontend_proposal_num"
795+
git push "$REPO_HTTPS_URL" "proposal-frontend-$frontend_proposal_num"
758796
fi
759797
fi
760798
}
@@ -772,10 +810,10 @@ UPGRADE_TYPE="$(checklist_must_get 'Upgrade type')"
772810
echo "Upgrade type: $UPGRADE_TYPE"
773811
echo ""
774812

775-
confirm_cmd git fetch --tags --force
813+
confirm_cmd git fetch "$REPO_HTTPS_URL" --tags --force
776814
confirm_cmd git tag -f $TAG_NAME
777815
record "Release commit" git rev-parse $TAG_NAME
778-
record "New tag pushed" git push origin $TAG_NAME
816+
record "New tag pushed" git push "$REPO_HTTPS_URL" $TAG_NAME
779817
confirm_cmd wait_for_release
780818
confirm_manual "Review release page update" update_release_text
781819

@@ -811,7 +849,12 @@ confirm_manual "Test release candidate" test_release_candidate
811849

812850
# --- Production: prepare proposal arguments ---
813851
confirm_cmd download_proposal_text
814-
confirm_cmd prepare_proposal_argument
852+
if should_upgrade_backend "$UPGRADE_TYPE"; then
853+
confirm_cmd prepare_production_backend_argument
854+
fi
855+
if should_upgrade_frontend "$UPGRADE_TYPE"; then
856+
confirm_cmd prepare_production_frontend_argument
857+
fi
815858
confirm_cmd append_proposal_argument
816859
confirm_manual "Confirm proposal arguments" confirm_proposal_arguments
817860
confirm_manual "Share proposal contents on Slack" share_proposal

0 commit comments

Comments
 (0)