From 9b1d8068166dac0784d4500e6387d221a072ae3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:21:36 +0000 Subject: [PATCH 01/11] fix(ci): scope GIT_CONFIG vars to wrapper subshell only setup-git-for-yarn previously echoed GIT_CONFIG_GLOBAL=/dev/null (and HOME, XDG_CONFIG_HOME, GIT_CONFIG_NOSYSTEM, GIT_CONFIG_SYSTEM, GIT_CONFIG_COUNT) into $GITHUB_ENV. That propagates to every subsequent step in the job, breaking any downstream "git config --global ..." call: the write lands in /dev/null and the read returns empty. The reusable Solidity docs workflow exercises this path: it calls "git config --global user.email/name" after this action runs, then "git commit -S". Both fail when the global config target is /dev/null. Move the GIT_CONFIG_* sanitisation entirely inside the wrapper script (it already unsets them and exports clean values per invocation, scoped to the git child process). The job env retains only GIT and npm_config_git, which point downstream tooling at the wrapper without poisoning git's config resolution for unrelated steps. --- .github/actions/setup-git-for-yarn/action.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/actions/setup-git-for-yarn/action.yml b/.github/actions/setup-git-for-yarn/action.yml index 39258ec76a..cbb36c167b 100644 --- a/.github/actions/setup-git-for-yarn/action.yml +++ b/.github/actions/setup-git-for-yarn/action.yml @@ -36,14 +36,13 @@ runs: "exec \"${REAL_GIT}\" \"\$@\"" \ >"${WRAPPER_DIR}/git" chmod +x "${WRAPPER_DIR}/git" + # Only export the git-binary indirection vars to the job env. The + # wrapper itself re-creates a clean GIT_CONFIG_* environment on every + # invocation, so downstream steps that legitimately need to write + # global git config (e.g. docs publish setting user.email/name) are + # not silently redirected to /dev/null. { echo "GIT=${WRAPPER_DIR}/git" echo "npm_config_git=${WRAPPER_DIR}/git" - echo "HOME=${SAFE_HOME}" - echo "XDG_CONFIG_HOME=${SAFE_XDG_CONFIG_HOME}" - echo "GIT_CONFIG_GLOBAL=/dev/null" - echo "GIT_CONFIG_NOSYSTEM=1" - echo "GIT_CONFIG_SYSTEM=/dev/null" - echo "GIT_CONFIG_COUNT=0" } >> "$GITHUB_ENV" echo "${WRAPPER_DIR}" >> "$GITHUB_PATH" From fa888a088592e861e51fc145a8d9d94a5e2a7343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:23:48 +0000 Subject: [PATCH 02/11] refactor(ci): extract Yarn install into composite action The PR introduced setup-git-for-yarn to centralise git-wrapping for Corepack/Yarn installs, but each workflow still duplicated a ~22-line shell block that exported PATH, scrubbed GIT_CONFIG_*, ran corepack, and invoked yarn install --immutable. That block appeared 13 times across four workflows. Move the install incantation into .github/actions/install-yarn-deps, which takes a working-directory input and also runs setup-git-for-yarn internally so callers do not need a separate step. Each duplicated block collapses to a single `uses:` reference. npm-random-beacon.yml is intentionally left alone in this commit: it runs `yarn upgrade` rather than `yarn install --immutable`, so it does not match the install incantation pattern. Net diff: -351 / +42 across four workflows. --- .github/actions/install-yarn-deps/action.yml | 37 ++++ .github/workflows/contracts-ecdsa.yml | 168 ++---------------- .github/workflows/contracts-random-beacon.yml | 168 ++---------------- .github/workflows/npm-ecdsa.yml | 28 +-- .github/workflows/reusable-solidity-docs.yml | 29 +-- 5 files changed, 79 insertions(+), 351 deletions(-) create mode 100644 .github/actions/install-yarn-deps/action.yml diff --git a/.github/actions/install-yarn-deps/action.yml b/.github/actions/install-yarn-deps/action.yml new file mode 100644 index 0000000000..ab3ac6c901 --- /dev/null +++ b/.github/actions/install-yarn-deps/action.yml @@ -0,0 +1,37 @@ +name: Install Yarn dependencies (Yarn 4 / Corepack) +description: > + Enable Corepack, set up the Git-for-Yarn wrapper, and run + `yarn install --immutable` in the given workspace. Centralises the + install incantation so each workflow does not need to re-export PATH, + GIT_CONFIG_*, or pin the Corepack-managed Yarn version. +inputs: + working-directory: + description: "Workspace directory containing package.json and yarn.lock." + required: true +runs: + using: composite + steps: + - name: Set up Git wrapper for Yarn git dependencies + uses: ./.github/actions/setup-git-for-yarn + + - name: Install dependencies + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + set -euo pipefail + export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" + export YARN_ENABLE_HARDENED_MODE=0 + export YARN_CHECKSUM_BEHAVIOR=ignore + corepack enable + yarn --version + unset_args=() + while IFS='=' read -r key _; do + case "$key" in + GIT_CONFIG_*) unset_args+=("-u" "$key") ;; + esac + done < <(env) + env "${unset_args[@]}" \ + GIT_CONFIG_NOSYSTEM=1 \ + GIT_CONFIG_SYSTEM=/dev/null \ + GIT_CONFIG_COUNT=0 \ + yarn install --immutable diff --git a/.github/workflows/contracts-ecdsa.yml b/.github/workflows/contracts-ecdsa.yml index 0b8ad2c644..269bb19a2f 100644 --- a/.github/workflows/contracts-ecdsa.yml +++ b/.github/workflows/contracts-ecdsa.yml @@ -57,31 +57,9 @@ jobs: # https://github.com/NomicFoundation/hardhat/issues/3877 node-version: "18.15.0" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/ecdsa - name: Build run: yarn build @@ -122,31 +100,9 @@ jobs: SLITHER_VERSION: 0.8.3 run: pip3 install slither-analyzer==$SLITHER_VERSION - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/ecdsa # As a workaround for a slither issue https://github.com/crytic/slither/issues/1140 # we disable compilation of dependencies when running slither. @@ -169,31 +125,9 @@ jobs: # https://github.com/NomicFoundation/hardhat/issues/3877 node-version: "18.15.0" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/ecdsa - name: Build solidity contracts run: yarn build @@ -218,31 +152,9 @@ jobs: # https://github.com/NomicFoundation/hardhat/issues/3877 node-version: "18.15.0" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/ecdsa - name: Deploy contracts run: yarn deploy:test @@ -274,31 +186,9 @@ jobs: node-version: "18.15.0" registry-url: "https://registry.npmjs.org" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/ecdsa - name: Get upstream packages versions uses: keep-network/ci/actions/upstream-builds-query@v2 @@ -396,31 +286,9 @@ jobs: node-version: "18.15.0" registry-url: "https://registry.npmjs.org" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/ecdsa - name: Get upstream packages versions uses: keep-network/ci/actions/upstream-builds-query@v2 diff --git a/.github/workflows/contracts-random-beacon.yml b/.github/workflows/contracts-random-beacon.yml index 8e49a0c3a0..e30166b6cf 100644 --- a/.github/workflows/contracts-random-beacon.yml +++ b/.github/workflows/contracts-random-beacon.yml @@ -57,31 +57,9 @@ jobs: # https://github.com/NomicFoundation/hardhat/issues/3877 node-version: "18.15.0" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/random-beacon - name: Build run: yarn build @@ -122,31 +100,9 @@ jobs: SLITHER_VERSION: 0.8.3 run: pip3 install slither-analyzer==$SLITHER_VERSION - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/random-beacon - name: Run Slither run: slither . @@ -167,31 +123,9 @@ jobs: # https://github.com/NomicFoundation/hardhat/issues/3877 node-version: "18.15.0" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/random-beacon - name: Build solidity contracts run: yarn build @@ -216,31 +150,9 @@ jobs: # https://github.com/NomicFoundation/hardhat/issues/3877 node-version: "18.15.0" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/random-beacon - name: Deploy contracts run: yarn deploy:test @@ -272,31 +184,9 @@ jobs: node-version: "18.15.0" registry-url: "https://registry.npmjs.org" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/random-beacon - name: Get upstream packages versions uses: keep-network/ci/actions/upstream-builds-query@v2 @@ -392,31 +282,9 @@ jobs: node-version: "18.15.0" registry-url: "https://registry.npmjs.org" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/random-beacon - name: Get upstream packages versions uses: keep-network/ci/actions/upstream-builds-query@v2 diff --git a/.github/workflows/npm-ecdsa.yml b/.github/workflows/npm-ecdsa.yml index a05845986b..f069ce2ba7 100644 --- a/.github/workflows/npm-ecdsa.yml +++ b/.github/workflows/npm-ecdsa.yml @@ -31,31 +31,9 @@ jobs: node-version: "18.15.0" registry-url: "https://registry.npmjs.org" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: ./solidity/ecdsa # Deploy contracts to a local network to generate deployment artifacts that # are required by dashboard and client compilation. diff --git a/.github/workflows/reusable-solidity-docs.yml b/.github/workflows/reusable-solidity-docs.yml index 7f01a6a5d3..3578ac4273 100644 --- a/.github/workflows/reusable-solidity-docs.yml +++ b/.github/workflows/reusable-solidity-docs.yml @@ -127,32 +127,9 @@ jobs: with: node-version: "18.15.0" - - uses: ./.github/actions/setup-git-for-yarn - - - name: Install dependencies - shell: bash - run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore - corepack enable - corepack prepare yarn@4.8.1 --activate - yarn --version - unset_args=() - while IFS='=' read -r key _; do - case "$key" in - GIT_CONFIG_*) unset_args+=("-u" "$key") ;; - esac - done < <(env) - env "${unset_args[@]}" \ - GIT_CONFIG_NOSYSTEM=1 \ - GIT_CONFIG_SYSTEM=/dev/null \ - GIT_CONFIG_COUNT=0 \ - yarn install --immutable + - uses: ./.github/actions/install-yarn-deps + with: + working-directory: .${{ inputs.projectDir }} - name: Build Markdown docs run: yarn run hardhat docgen From 29954b1f14712aaa98c19c931a36e548085c13bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:24:08 +0000 Subject: [PATCH 03/11] ci: restore Yarn dependency caching via actions/cache The PR removed setup-node's "cache: yarn" / cache-dependency-path directives across every workflow without a replacement. Yarn 4 stores its content-addressable cache under .yarn/cache (gitignored), so every CI job was re-downloading the full dependency set on every run. Add actions/cache@v4 to the install-yarn-deps composite action, keyed on the workspace's yarn.lock hash. Cache covers .yarn/cache, .yarn/install-state.gz, and node_modules (the workspace uses the node-modules linker). A restore-keys fallback prevents cold-start runs from blocking on a cache miss. --- .github/actions/install-yarn-deps/action.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/actions/install-yarn-deps/action.yml b/.github/actions/install-yarn-deps/action.yml index ab3ac6c901..cfbdfd0119 100644 --- a/.github/actions/install-yarn-deps/action.yml +++ b/.github/actions/install-yarn-deps/action.yml @@ -14,6 +14,17 @@ runs: - name: Set up Git wrapper for Yarn git dependencies uses: ./.github/actions/setup-git-for-yarn + - name: Cache Yarn artifacts + uses: actions/cache@v4 + with: + path: | + ${{ inputs.working-directory }}/.yarn/cache + ${{ inputs.working-directory }}/.yarn/install-state.gz + ${{ inputs.working-directory }}/node_modules + key: yarn-${{ runner.os }}-${{ hashFiles(format('{0}/yarn.lock', inputs.working-directory)) }} + restore-keys: | + yarn-${{ runner.os }}- + - name: Install dependencies shell: bash working-directory: ${{ inputs.working-directory }} From 7867502a81944916c680d9fa8cff16ad9a9c22be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:24:51 +0000 Subject: [PATCH 04/11] fix(ci): re-enable Yarn lockfile integrity checks YARN_ENABLE_HARDENED_MODE=0 and YARN_CHECKSUM_BEHAVIOR=ignore turn off Yarn 4's lockfile-integrity verification (poisoned-package detection, checksum mismatch detection). Migrating to Yarn 4 specifically to disable its safety features defeats the supply-chain rationale for the upgrade. The lockfile already carries integrity hashes for the codeload tarballs; ignoring them silences the alarm that would catch real tampering. Drop both env vars from install-yarn-deps and from the previously-dead per-step exports in npm-random-beacon.yml's "Enable Yarn 4" step. If a future "yarn install --immutable" fails with a checksum mismatch, that is a real signal to regenerate the lockfile, not to silence the check. --- .github/actions/install-yarn-deps/action.yml | 2 -- .github/workflows/npm-random-beacon.yml | 8 -------- 2 files changed, 10 deletions(-) diff --git a/.github/actions/install-yarn-deps/action.yml b/.github/actions/install-yarn-deps/action.yml index cfbdfd0119..bd89f79024 100644 --- a/.github/actions/install-yarn-deps/action.yml +++ b/.github/actions/install-yarn-deps/action.yml @@ -31,8 +31,6 @@ runs: run: | set -euo pipefail export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore corepack enable yarn --version unset_args=() diff --git a/.github/workflows/npm-random-beacon.yml b/.github/workflows/npm-random-beacon.yml index e372991185..7e08af6737 100644 --- a/.github/workflows/npm-random-beacon.yml +++ b/.github/workflows/npm-random-beacon.yml @@ -35,15 +35,7 @@ jobs: - name: Enable Yarn 4 (packageManager) run: | - export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" - unset GIT_CONFIG_PARAMETERS - export GIT_CONFIG_NOSYSTEM=1 - export GIT_CONFIG_SYSTEM=/dev/null - export GIT_CONFIG_COUNT=0 - export YARN_ENABLE_HARDENED_MODE=0 - export YARN_CHECKSUM_BEHAVIOR=ignore corepack enable - corepack prepare yarn@4.8.1 --activate yarn --version - name: Resolve latest contracts From a6cf6ff26cce7edc68f74c4ccf199daa8bb86793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:25:12 +0000 Subject: [PATCH 05/11] fix(workflows): replace unmaintained hub with gh pr create The reusable Solidity docs workflow used \`hub pull-request\` to open a PR against the destination docs repo. The hub CLI is unmaintained and was removed from ubuntu-22.04 runner images in 2024; it is not present on ubuntu-24.04 images at all. The publish path would fail at runtime the moment GitHub rolls the runner image forward. gh is preinstalled on every hosted runner and is the modern replacement. --- .github/workflows/reusable-solidity-docs.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-solidity-docs.yml b/.github/workflows/reusable-solidity-docs.yml index 3578ac4273..a58ebc0308 100644 --- a/.github/workflows/reusable-solidity-docs.yml +++ b/.github/workflows/reusable-solidity-docs.yml @@ -216,9 +216,12 @@ jobs: "https://api.github.com/repos/${{ inputs.destinationRepo }}/pulls?status=open&head=$dest_org:$head_branch") if [[ $pr_for_head == $'[\n\n]' ]]; then echo "➞ Checked. A PR for the head branch ($head_branch) will be created" - hub pull-request --base $base_branch \ - --message "Update Solidity API docs" \ - --message "Docs updated by workflow: https://github.com/${{ github.repository}}/actions/runs/${{ github.run_id}}" + gh pr create \ + --repo "${{ inputs.destinationRepo }}" \ + --base "$base_branch" \ + --head "$head_branch" \ + --title "Update Solidity API docs" \ + --body "Docs updated by workflow: https://github.com/${{ github.repository}}/actions/runs/${{ github.run_id}}" else echo "➞ Checked. A PR for head branch ($head_branch) already exists and got updated." fi From 0c341648fdbcd54d0de029c14404ad4d7d5c2137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:25:50 +0000 Subject: [PATCH 06/11] fix(workflows): use gh credential helper instead of token-in-URL The clone step embedded \$GITHUB_TOKEN directly into the HTTPS URL. That token ends up persisted in remote.origin.url inside the cloned repo's .git/config and is visible in any \`git remote -v\` output or process listing during the clone. GitHub Actions redacts known secret strings from job logs, but the token still lands on disk on the runner and in process arguments. Configure gh as a git credential helper for github.com via \`gh auth setup-git\`. gh reads GH_TOKEN from the environment and supplies credentials on demand, so the clone URL stays token-free and the cloned repo's .git/config does not retain credentials. --- .github/workflows/reusable-solidity-docs.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reusable-solidity-docs.yml b/.github/workflows/reusable-solidity-docs.yml index a58ebc0308..4e93d4fc8a 100644 --- a/.github/workflows/reusable-solidity-docs.yml +++ b/.github/workflows/reusable-solidity-docs.yml @@ -182,13 +182,16 @@ jobs: if: inputs.publish == true env: GITHUB_TOKEN: ${{ secrets.githubToken }} + GH_TOKEN: ${{ secrets.githubToken }} run: | echo "➞ Configure environment variables" head_branch=auto-update-solidity-api-docs base_branch=${{ inputs.destinationBaseBranch }} + echo "➞ Configure gh as git credential helper (keeps token out of URLs and .git/config)" + gh auth setup-git --hostname github.com echo "➞ Checkout destination repo" git clone --branch $base_branch \ - https://${{ inputs.userName }}:$GITHUB_TOKEN@github.com/${{ inputs.destinationRepo }}.git \ + https://github.com/${{ inputs.destinationRepo }}.git \ dest-repo-clone echo "➞ Create/checkout head branch" cd dest-repo-clone From d8bf0becd924094dcdae05ae271184f7f5eb4e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:26:04 +0000 Subject: [PATCH 07/11] ci(workflows): pin upload-artifact to v4 actions/upload-artifact@master is unpinned: any change pushed to the action's master branch ships immediately into every CI run, with no review. Pin to v4 (current major), which also matches GitHub's recommended supply-chain hygiene for third-party actions. The two upload-artifact callsites use distinct artifact names ("contracts-after-preprocessing" and "contracts-final-output"), so the v4 breaking change around per-name uniqueness does not apply. --- .github/workflows/reusable-solidity-docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-solidity-docs.yml b/.github/workflows/reusable-solidity-docs.yml index 4e93d4fc8a..971bf4af13 100644 --- a/.github/workflows/reusable-solidity-docs.yml +++ b/.github/workflows/reusable-solidity-docs.yml @@ -114,7 +114,7 @@ jobs: - name: Export artifacts if: inputs.exportAsGHArtifacts == true - uses: actions/upload-artifact@master + uses: actions/upload-artifact@v4 with: name: contracts-after-preprocessing path: .${{ inputs.projectDir }}/contracts @@ -149,7 +149,7 @@ jobs: - name: Export artifacts if: inputs.exportAsGHArtifacts == true - uses: actions/upload-artifact@master + uses: actions/upload-artifact@v4 with: name: contracts-final-output path: .${{ inputs.projectDir }}/generated-docs From 091f703f8c4053ab45fdef4571b9e74fd64693ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 12:26:26 +0000 Subject: [PATCH 08/11] ci(workflows): bump checkout and setup-node to v4 in new docs workflow This file is newly introduced by this PR (previously sourced from keep-network/ci@main). Land it on current major versions of the GitHub-maintained actions rather than the deprecated v3 line. Scope deliberately limited to the new file: pre-existing v3 usage in contracts-*.yml / npm-*.yml is left untouched in this commit to keep the change surgical. --- .github/workflows/reusable-solidity-docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-solidity-docs.yml b/.github/workflows/reusable-solidity-docs.yml index 971bf4af13..0912c04a4b 100644 --- a/.github/workflows/reusable-solidity-docs.yml +++ b/.github/workflows/reusable-solidity-docs.yml @@ -96,7 +96,7 @@ jobs: run: working-directory: .${{ inputs.projectDir }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Prepare contract files for further processing if: inputs.trimComments @@ -123,7 +123,7 @@ jobs: shell: bash run: git config --global url."https://".insteadOf git:// - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: "18.15.0" From 7f7430974ae7974b11e3afb924a0a5846204ed66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 13:05:30 +0000 Subject: [PATCH 09/11] fix(ci): keep HARDENED_MODE disabled, documented CI surfaced that Yarn 4 auto-enables hardened mode on public PR contexts ("workflow is executed from a public pull request"), and ECDSA's lockfile contains a legitimate npm-descriptor -> git-URL remap that hardened mode rejects: YN0078: Invalid resolution ethereumjs-abi@npm:0.6.8 -> https://github.com/ethereumjs/ethereumjs-abi.git#commit=ee... The remap exists because ethereumjs-abi@0.6.8 was published broken on npm; the canonical fix is the git pin, and that is what the lockfile encodes. Hardened mode considers all npm->git remaps a supply-chain risk, with no per-entry opt-in. Restore YARN_ENABLE_HARDENED_MODE=0 with a comment explaining the reason. Keep YARN_CHECKSUM_BEHAVIOR at its default (the previous \`=ignore\` was unnecessary; per-package integrity hashes are still enforced). Verified locally: \`yarn install --immutable\` succeeds in solidity/ecdsa with this configuration, fails with YN0078 without it. --- .github/actions/install-yarn-deps/action.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/actions/install-yarn-deps/action.yml b/.github/actions/install-yarn-deps/action.yml index bd89f79024..3a3725fb04 100644 --- a/.github/actions/install-yarn-deps/action.yml +++ b/.github/actions/install-yarn-deps/action.yml @@ -31,6 +31,16 @@ runs: run: | set -euo pipefail export PATH="${RUNNER_TEMP:-/tmp}/git-clean-bin:$PATH" + # Opt out of Yarn 4 hardened mode. Yarn auto-enables it on public PR + # contexts; we cannot use it here because the lockfiles contain + # legitimate npm-descriptor -> git-URL remaps (e.g. ethereumjs-abi + # @npm:0.6.8 -> github.com/ethereumjs/ethereumjs-abi.git#, + # because npm 0.6.8 was published broken). Hardened mode rejects all + # such remaps as potential supply-chain attacks, even when the + # remap is internally consistent with the rest of the lockfile. + # Note: lockfile checksums remain enforced (YARN_CHECKSUM_BEHAVIOR + # is left at its default), so per-package integrity is still checked. + export YARN_ENABLE_HARDENED_MODE=0 corepack enable yarn --version unset_args=() From a67740b992a4629602315c5330dd2076af3196f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?= Date: Thu, 4 Jun 2026 13:28:53 +0000 Subject: [PATCH 10/11] fix(deps): pin @threshold-network/solidity-contracts to 1.3.0-dev.14 Both Solidity workspaces resolved @threshold-network/solidity-contracts via the floating "development" dist-tag, which has advanced to 1.3.0-dev.15+ and dropped a set of legacy TokenStaking methods that the test and deployment code still depend on: - test/utils/operators.ts: TokenStaking.stake, .increaseAuthorization - test/fixtures/index.ts: TokenStaking.pushNotificationReward, .setNotificationReward - deploy/*_approve_*.ts: TokenStaking.approveApplication Symptoms in CI: TS2551: Property 'stake' does not exist on type 'TokenStaking' TS2339: Property 'increaseAuthorization' does not exist on type ... TS2339: Property 'pushNotificationReward' does not exist on type ... TS2339: Property 'setNotificationReward' does not exist on type ... Error: No method named "approveApplication" on contract deployed as "TokenStaking" 1.3.0-dev.14 is the last published version that still ships all five methods (verified by inspecting TokenStaking.sol in each published tarball). Pin both workspaces to that exact version so CI is deterministic regardless of future dist-tag movement. Lockfiles regenerated. Verified locally: yarn install --immutable succeeds, hardhat compile + typechain + test compile pass without the TS2339/TS2551 errors above. --- solidity/ecdsa/package.json | 2 +- solidity/ecdsa/yarn.lock | 10 +++++----- solidity/random-beacon/package.json | 2 +- solidity/random-beacon/yarn.lock | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/solidity/ecdsa/package.json b/solidity/ecdsa/package.json index d860f68d9c..9f09822e3f 100644 --- a/solidity/ecdsa/package.json +++ b/solidity/ecdsa/package.json @@ -78,7 +78,7 @@ "@keep-network/sortition-pools": "^2.0.0-pre.16", "@openzeppelin/contracts": "^4.9.6", "@openzeppelin/contracts-upgradeable": "^4.9.6", - "@threshold-network/solidity-contracts": "development" + "@threshold-network/solidity-contracts": "1.3.0-dev.14" }, "engines": { "node": ">=18.15.0" diff --git a/solidity/ecdsa/yarn.lock b/solidity/ecdsa/yarn.lock index 24d9a991b9..386e48fb7d 100644 --- a/solidity/ecdsa/yarn.lock +++ b/solidity/ecdsa/yarn.lock @@ -1450,7 +1450,7 @@ __metadata: "@openzeppelin/hardhat-upgrades": "npm:^1.20.4" "@tenderly/hardhat-tenderly": "npm:>=1.0.13 <1.2.0" "@thesis-co/eslint-config": "https://codeload.github.com/thesis/eslint-config/tar.gz/778365bbebb6b056bf973d25c57b8b466d21cbcf" - "@threshold-network/solidity-contracts": "npm:development" + "@threshold-network/solidity-contracts": "npm:1.3.0-dev.14" "@typechain/ethers-v5": "npm:^8.0.5" "@typechain/hardhat": "npm:^4.0.0" "@types/chai": "npm:^4.3.0" @@ -2187,14 +2187,14 @@ __metadata: languageName: node linkType: hard -"@threshold-network/solidity-contracts@npm:development": - version: 1.3.0-dev.16 - resolution: "@threshold-network/solidity-contracts@npm:1.3.0-dev.16" +"@threshold-network/solidity-contracts@npm:1.3.0-dev.14": + version: 1.3.0-dev.14 + resolution: "@threshold-network/solidity-contracts@npm:1.3.0-dev.14" dependencies: "@openzeppelin/contracts": "npm:~4.5.0" "@openzeppelin/contracts-upgradeable": "npm:~4.5.2" "@thesis/solidity-contracts": "github:thesis/solidity-contracts#4985bcf" - checksum: 10c0/25d67883e11417fc1e8413ec6d9470b164bc459d262514199f8baa4165f782773793b6a38235026ed31e9c6a3d846efef58b5317ea80f9c59306266879548368 + checksum: 10c0/8b4f942f92a3ed6e27665bd164e45b96c13d2d6f3422e8733d3b4a382fa02b14dbf79b9843f31289a079d1cbadfd557b4bd1f75e42b95d5861011412123f32d7 languageName: node linkType: hard diff --git a/solidity/random-beacon/package.json b/solidity/random-beacon/package.json index 5e7473d886..ece2aee6f0 100644 --- a/solidity/random-beacon/package.json +++ b/solidity/random-beacon/package.json @@ -37,7 +37,7 @@ "@keep-network/sortition-pools": "^2.0.0-pre.16", "@openzeppelin/contracts": "4.7.3", "@thesis/solidity-contracts": "github:thesis/solidity-contracts#4985bcf", - "@threshold-network/solidity-contracts": "development" + "@threshold-network/solidity-contracts": "1.3.0-dev.14" }, "devDependencies": { "@defi-wonderland/smock": "^2.0.7", diff --git a/solidity/random-beacon/yarn.lock b/solidity/random-beacon/yarn.lock index dd0fcc5e44..bcdba596a8 100644 --- a/solidity/random-beacon/yarn.lock +++ b/solidity/random-beacon/yarn.lock @@ -1217,7 +1217,7 @@ __metadata: "@tenderly/hardhat-tenderly": "npm:1.0.12" "@thesis-co/eslint-config": "https://codeload.github.com/thesis/eslint-config/tar.gz/e63608fab2a1ad5c8fe89873bf0d4d4f9ef4a081" "@thesis/solidity-contracts": "github:thesis/solidity-contracts#4985bcf" - "@threshold-network/solidity-contracts": "npm:development" + "@threshold-network/solidity-contracts": "npm:1.3.0-dev.14" "@typechain/ethers-v5": "npm:^9.0.0" "@typechain/hardhat": "npm:^4.0.0" "@types/chai": "npm:^4.2.22" @@ -1741,14 +1741,14 @@ __metadata: languageName: node linkType: hard -"@threshold-network/solidity-contracts@npm:development": - version: 1.3.0-dev.16 - resolution: "@threshold-network/solidity-contracts@npm:1.3.0-dev.16" +"@threshold-network/solidity-contracts@npm:1.3.0-dev.14": + version: 1.3.0-dev.14 + resolution: "@threshold-network/solidity-contracts@npm:1.3.0-dev.14" dependencies: "@openzeppelin/contracts": "npm:~4.5.0" "@openzeppelin/contracts-upgradeable": "npm:~4.5.2" "@thesis/solidity-contracts": "github:thesis/solidity-contracts#4985bcf" - checksum: 10c0/25d67883e11417fc1e8413ec6d9470b164bc459d262514199f8baa4165f782773793b6a38235026ed31e9c6a3d846efef58b5317ea80f9c59306266879548368 + checksum: 10c0/8b4f942f92a3ed6e27665bd164e45b96c13d2d6f3422e8733d3b4a382fa02b14dbf79b9843f31289a079d1cbadfd557b4bd1f75e42b95d5861011412123f32d7 languageName: node linkType: hard From a20e1813da174e3d7119739d4a27a78771d76301 Mon Sep 17 00:00:00 2001 From: Leonardo Saturnino Date: Fri, 5 Jun 2026 23:35:23 -0300 Subject: [PATCH 11/11] fix(ci): use real git for Solidity docs publishing steps The docs-publish path in reusable-solidity-docs.yml runs its git operations through the Yarn git wrapper that setup-git-for-yarn installs on $PATH and exports as $GIT/$npm_config_git for the whole job. The wrapper forces GIT_CONFIG_GLOBAL=/dev/null with a throwaway HOME on every git invocation, so the docs-sync step fails: gh auth setup-git and the git config --global user.email/name calls cannot write the global config ("could not lock config file /dev/null"), the credential helper is never registered, and the authenticated git push has no credentials. The earlier token-in-URL approach survived the wrapper because the credentials lived in the URL rather than git config; moving to the credential helper made the path secure but non-functional. The wrapper is only needed so yarn install can clone git dependencies, which has already happened by the time docs are generated. Add a publish-only step that removes the wrapper binary and repoints $GIT/$npm_config_git at the real git for the remaining publishing steps, restoring the intended credential-helper and tokenless-URL design with no changes to the existing steps. This path is release-gated (publish == true on a solidity/* release tag) and is not exercised by normal PR or preview runs, so it was verified by static analysis and a local reproduction of the /dev/null config-lock failure rather than an end-to-end release run. --- .github/workflows/reusable-solidity-docs.yml | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/reusable-solidity-docs.yml b/.github/workflows/reusable-solidity-docs.yml index 0912c04a4b..0771fcc522 100644 --- a/.github/workflows/reusable-solidity-docs.yml +++ b/.github/workflows/reusable-solidity-docs.yml @@ -169,6 +169,32 @@ jobs: body: 'Solidity API documentation preview available in the artifacts of the https://github.com/${{ github.repository}}/actions/runs/${{ github.run_id}} check.' }) + - name: Use real git for publishing steps (bypass Yarn git wrapper) + if: inputs.publish == true + shell: bash + run: | + # The Yarn git wrapper (.github/actions/setup-git-for-yarn) is placed on + # $PATH and exported as $GIT / $npm_config_git for the whole job so + # `yarn install` can clone git dependencies. Every git it intercepts is + # forced to GIT_CONFIG_GLOBAL=/dev/null with a throwaway $HOME. That + # breaks the docs-sync step below: `gh auth setup-git` and the + # `git config --global user.email/name` calls cannot write the global + # config ("could not lock config file /dev/null"), so the credential + # helper is never registered and the authenticated `git push` has no + # credentials. Docs publishing does not need the wrapper — `yarn install` + # already ran during doc generation — so remove it and point git back at + # the real binary for the remaining publishing steps. Scoped to + # publish == true, so the preview path and non-docs callers are + # unaffected. + set -euo pipefail + rm -f "${RUNNER_TEMP:-/tmp}/git-clean-bin/git" + real_git="$(command -v git)" + { + echo "GIT=${real_git}" + echo "npm_config_git=${real_git}" + } >> "$GITHUB_ENV" + echo "Bypassed Yarn git wrapper for publishing; git=${real_git}" + - name: Import GPG key if: inputs.publish == true && inputs.verifyCommits == true uses: crazy-max/ghaction-import-gpg@111c56156bcc6918c056dbef52164cfa583dc549