From 901e527a18a1c955d37d8fccf1367a646f495d77 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 18 Aug 2026 11:47:01 -0400 Subject: [PATCH 1/3] ci: extend dependency-update workflow to example apps Check every SDK-consuming package (root plus each example app) against the latest @dashevo/evo-sdk release, bump the ones that are behind with lock-only installs, and keep each app's standalone lite page importing the exact version its package.json pins. Also harden the script with set -euo pipefail, npm ci, and validation of versions read from npm and lockfiles. --- .github/workflows/dependency-update.yml | 149 +++++++++++++++++------- 1 file changed, 107 insertions(+), 42 deletions(-) diff --git a/.github/workflows/dependency-update.yml b/.github/workflows/dependency-update.yml index 337bb90b..5f7c737a 100644 --- a/.github/workflows/dependency-update.yml +++ b/.github/workflows/dependency-update.yml @@ -29,52 +29,113 @@ jobs: node -v npm -v - # Step 3: Install dependencies - - name: Install Dependencies - run: npm install - - # Step 4: Check and Update @dashevo/evo-sdk Dependency and Version - - name: Check and Update @dashevo/evo-sdk Dependency + # Step 3: Check and update every package that uses @dashevo/evo-sdk + - name: Check and Update @dashevo/evo-sdk Dependencies id: update_evo_sdk run: | - set -e # Stop execution on any error - - # Get the installed version from the lockfile (not the declared specifier) - INSTALLED_VERSION=$(npm ls @dashevo/evo-sdk --json | jq -r '.dependencies["@dashevo/evo-sdk"].version') - CURRENT_DASH_VERSION=$(jq -r '.dependencies["@dashevo/evo-sdk"] // .devDependencies["@dashevo/evo-sdk"]' package.json) - DASH_PREFIX=$(echo "$CURRENT_DASH_VERSION" | grep -o '^[^0-9]*') - - # Get the latest version of Dash - LATEST_DASH_VERSION=$(npm show @dashevo/evo-sdk version) - LATEST_MINOR_PATCH=$(echo "$LATEST_DASH_VERSION" | cut -d. -f2,3) - - echo "Installed @dashevo/evo-sdk version: $INSTALLED_VERSION" - echo "Latest @dashevo/evo-sdk version: $LATEST_DASH_VERSION" - - # Only update if the latest stable version is strictly higher than installed - # npx semver returns the version if it satisfies the range, empty otherwise - IS_HIGHER=$(npx -y semver "$LATEST_DASH_VERSION" -r ">$INSTALLED_VERSION" || true) - - if [ -n "$IS_HIGHER" ]; then - jq '.dependencies["@dashevo/evo-sdk"] = "'"$DASH_PREFIX$LATEST_DASH_VERSION"'"' package.json > package.json.tmp && mv package.json.tmp package.json + set -euo pipefail - # Update package version in package.json (keep major version, sync minor and patch) - CURRENT_PACKAGE_VERSION=$(jq -r '.version' package.json) - CURRENT_MAJOR_VERSION=$(echo "$CURRENT_PACKAGE_VERSION" | cut -d. -f1) - NEW_PACKAGE_VERSION="$CURRENT_MAJOR_VERSION.$LATEST_MINOR_PATCH" - - jq '.version = "'"$NEW_PACKAGE_VERSION"'"' package.json > package.json.tmp && mv package.json.tmp package.json - echo "Updated package.json version to $NEW_PACKAGE_VERSION" - - npm install @dashevo/evo-sdk + latest_version="$(npm show @dashevo/evo-sdk version)" + if ! npx -y semver "$latest_version" >/dev/null; then + echo "Invalid latest @dashevo/evo-sdk version returned by npm: $latest_version" >&2 + exit 1 + fi + echo "Latest @dashevo/evo-sdk version: $latest_version" + + locked_version() { + local package_dir="$1" + local lockfile="$package_dir/package-lock.json" + + if [ ! -f "$lockfile" ]; then + echo "Missing lockfile for SDK-consuming package: $lockfile" >&2 + return 1 + fi + + local version + version="$(jq -r \ + '.packages["node_modules/@dashevo/evo-sdk"].version // .dependencies["@dashevo/evo-sdk"].version // empty' \ + "$lockfile")" + if [ -z "$version" ] || ! npx -y semver "$version" >/dev/null; then + echo "Missing or invalid @dashevo/evo-sdk version in $lockfile: ${version:-}" >&2 + return 1 + fi + echo "$version" + } + + is_behind() { + local version="$1" + [ -n "$(npx -y semver "$latest_version" -r ">$version" || true)" ] + } + + update_dependency_specifier() { + local package_file="$1" + local specifier="$2" + jq --arg version "$specifier" ' + if .dependencies["@dashevo/evo-sdk"] then + .dependencies["@dashevo/evo-sdk"] = $version + elif .devDependencies["@dashevo/evo-sdk"] then + .devDependencies["@dashevo/evo-sdk"] = $version + else + error("package does not declare @dashevo/evo-sdk") + end + ' "$package_file" > "$package_file.tmp" + mv "$package_file.tmp" "$package_file" + } + + updated_packages=() + root_locked_version="$(locked_version .)" + echo "Root locked version: $root_locked_version" + if is_behind "$root_locked_version"; then + current_specifier="$(jq -r '.dependencies["@dashevo/evo-sdk"] // .devDependencies["@dashevo/evo-sdk"]' package.json)" + version_prefix="$(echo "$current_specifier" | grep -o '^[^0-9]*' || true)" + update_dependency_specifier package.json "$version_prefix$latest_version" + + current_package_version="$(jq -r '.version' package.json)" + current_major_version="${current_package_version%%.*}" + latest_minor_patch="${latest_version#*.}" + new_package_version="$current_major_version.$latest_minor_patch" + jq --arg version "$new_package_version" '.version = $version' package.json > package.json.tmp + mv package.json.tmp package.json + + npm install --package-lock-only --ignore-scripts + updated_packages+=("root") + echo "Updated root SDK to $latest_version and package version to $new_package_version" + fi - echo "needs_update=true" >> $GITHUB_ENV + for package_file in example-apps/*/package.json; do + [ -f "$package_file" ] || continue + if ! jq -e '.dependencies["@dashevo/evo-sdk"] // .devDependencies["@dashevo/evo-sdk"]' "$package_file" >/dev/null; then + continue + fi + + package_dir="$(dirname "$package_file")" + app_name="$(basename "$package_dir")" + app_locked_version="$(locked_version "$package_dir")" + echo "$app_name locked version: $app_locked_version" + if is_behind "$app_locked_version"; then + # Apps use exact pins because their lite pages embed this specifier in an import URL. + update_dependency_specifier "$package_file" "$latest_version" + for page in "$package_dir"/public/*-lite.html; do + [ -f "$page" ] || continue + sed -i -E "s|(https://esm\.sh/@dashevo/evo-sdk@)[^'\"]+|\1$latest_version|" "$page" + done + (cd "$package_dir" && npm install --package-lock-only --ignore-scripts) + updated_packages+=("$app_name") + echo "Updated $app_name SDK to $latest_version" + fi + done + + if [ "${#updated_packages[@]}" -gt 0 ]; then + updated_list="$(printf ', %s' "${updated_packages[@]}")" + updated_list="${updated_list:2}" + echo "needs_update=true" >> "$GITHUB_ENV" + echo "updated_packages=$updated_list" >> "$GITHUB_ENV" else - echo "@dashevo/evo-sdk dependency is up-to-date" - echo "needs_update=false" >> $GITHUB_ENV + echo "All @dashevo/evo-sdk dependencies are up-to-date" + echo "needs_update=false" >> "$GITHUB_ENV" fi - # Step 5: Create Pull Request + # Step 4: Create Pull Request - name: Create Pull Request if: env.needs_update == 'true' uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 @@ -82,8 +143,12 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} branch: update-evo-sdk-and-version base: main - title: "chore: update @dashevo/evo-sdk dependency and sync version" + title: "chore: update @dashevo/evo-sdk across tutorials and examples" body: | - This pull request updates the `@dashevo/evo-sdk` dependency to the latest version and syncs the package version, aligning the minor and patch versions with `@dashevo/evo-sdk`. - commit-message: "chore: update @dashevo/evo-sdk dependency and sync version" + This pull request updates `@dashevo/evo-sdk` to the latest stable version across the tutorials and example apps. + + Updated packages: ${{ env.updated_packages }} + + When the root dependency changes, the root package version is also synchronized with the SDK minor and patch version. + commit-message: "chore: update @dashevo/evo-sdk across tutorials and examples" reviewers: "thephez" From 472e262e7bf367520fe09a4f2de580e7cd211508 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 18 Aug 2026 11:57:41 -0400 Subject: [PATCH 2/3] ci: address review feedback --- .github/workflows/dependency-update.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dependency-update.yml b/.github/workflows/dependency-update.yml index 5f7c737a..d8171f92 100644 --- a/.github/workflows/dependency-update.yml +++ b/.github/workflows/dependency-update.yml @@ -88,12 +88,17 @@ jobs: if is_behind "$root_locked_version"; then current_specifier="$(jq -r '.dependencies["@dashevo/evo-sdk"] // .devDependencies["@dashevo/evo-sdk"]' package.json)" version_prefix="$(echo "$current_specifier" | grep -o '^[^0-9]*' || true)" - update_dependency_specifier package.json "$version_prefix$latest_version" current_package_version="$(jq -r '.version' package.json)" current_major_version="${current_package_version%%.*}" latest_minor_patch="${latest_version#*.}" new_package_version="$current_major_version.$latest_minor_patch" + if [ -z "$(npx -y semver "$new_package_version" -r ">$current_package_version" || true)" ]; then + echo "Refusing non-forward package version update: $current_package_version -> $new_package_version" >&2 + exit 1 + fi + + update_dependency_specifier package.json "$version_prefix$latest_version" jq --arg version "$new_package_version" '.version = $version' package.json > package.json.tmp mv package.json.tmp package.json @@ -104,7 +109,7 @@ jobs: for package_file in example-apps/*/package.json; do [ -f "$package_file" ] || continue - if ! jq -e '.dependencies["@dashevo/evo-sdk"] // .devDependencies["@dashevo/evo-sdk"]' "$package_file" >/dev/null; then + if ! jq -e '.dependencies["@dashevo/evo-sdk"]' "$package_file" >/dev/null; then continue fi From 6ac0c63c0f328f3471f13a8532680597c5f9aee8 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 18 Aug 2026 12:06:55 -0400 Subject: [PATCH 3/3] ci: include sdk version in branch name Prevents conflicts with subsequent releases --- .github/workflows/dependency-update.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dependency-update.yml b/.github/workflows/dependency-update.yml index d8171f92..5dfe075d 100644 --- a/.github/workflows/dependency-update.yml +++ b/.github/workflows/dependency-update.yml @@ -135,6 +135,7 @@ jobs: updated_list="${updated_list:2}" echo "needs_update=true" >> "$GITHUB_ENV" echo "updated_packages=$updated_list" >> "$GITHUB_ENV" + echo "target_sdk_version=$latest_version" >> "$GITHUB_ENV" else echo "All @dashevo/evo-sdk dependencies are up-to-date" echo "needs_update=false" >> "$GITHUB_ENV" @@ -146,7 +147,7 @@ jobs: uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} - branch: update-evo-sdk-and-version + branch: update-evo-sdk-to-${{ env.target_sdk_version }} base: main title: "chore: update @dashevo/evo-sdk across tutorials and examples" body: |