Skip to content
Merged
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
145 changes: 105 additions & 40 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
version: 2.1

orbs:
slack: circleci/slack@3.4.2

Expand Down Expand Up @@ -61,7 +62,7 @@ jobs:
name: Install dependencies
command: bun install
- run:
name: Build Etherpot Modular SDK
name: Build Etherspot Modular SDK
command: bun run build
- run:
name: Checkout e2e repo and run tests
Expand All @@ -88,11 +89,13 @@ jobs:
sed -i.bak "s/secondary_wallet_address/$SECONDARY_WALLET_ADDRESS/g" .env
sed -i.bak "s/paymaster_address/$PAYMASTER_ADDRESS/g" .env
sed -i.bak "s/sponsor_address/$SPONSOR_ADDRESS/g" .env

mv package.json temp.json
jq -r '.dependencies."@etherspot/modular-sdk" |= "file:../etherspot-modular-sdk"' temp.json > package.json
rm temp.json

npm i
npm run test-all-chains
npm run test-all-chains
- store_artifacts:
path: /home/circleci/e2e-sdk-modular/reports
destination: test-report
Expand All @@ -107,6 +110,7 @@ jobs:
echo "❌ Aggregated mochawesome report not found at $MOCHAWESOME_JSON_FILE"
exit 0
fi

TOTAL_SUITES=$(jq '.stats.suites' $MOCHAWESOME_JSON_FILE)
TOTAL_PASSES=$(jq '.stats.passes' $MOCHAWESOME_JSON_FILE)
TOTAL_PENDING=$(jq '.stats.pending' $MOCHAWESOME_JSON_FILE)
Expand All @@ -119,64 +123,125 @@ jobs:
END_TIME_FORMATTED=$(date -d "$END_TIME" "+%Y-%m-%d %H:%M:%S")
DURATION_MIN=$(awk "BEGIN {printf \"%.2f\",${DURATION_MS}/60000}")


jq -r '.results[] | .suites[] | select(.failures > 0) | {suite: .title, tests: [.tests[] | select(.fail) | .title]} | select(.tests | length > 0) |
"*Suite:* \(.suite)\n*Failing Tests:* \n\(.tests | map("- " + .) | join("\n"))\n"' $MOCHAWESOME_JSON_FILE > $FAILED_TESTS_FILE

if [ -s $FAILED_TESTS_FILE ]; then
MESSAGE=$(cat $FAILED_TESTS_FILE)
SLACK_MESSAGE=":x: *E2E Tests Failed :x: *\n\
*Project:* ${CIRCLE_PROJECT_REPONAME}\n\
*Triggered by:* ${CIRCLE_USERNAME}\n\
*Branch:* ${CIRCLE_BRANCH}\n\
*Commit:* <https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}|${CIRCLE_SHA1}>\n\n\
*Test Summary:*\n\
*Total Suites:* ${TOTAL_SUITES}\n\
*Passes:* ${TOTAL_PASSES}\n\
*Pending:* ${TOTAL_PENDING}\n\
*Failures:* ${TOTAL_FAILURES}\n\
*Start Time:* ${START_TIME_FORMATTED}\n\
*End Time:* ${END_TIME_FORMATTED}\n\
*Duration:* ${DURATION_MIN} minutes\n\n\
*Failed Tests:*\n${MESSAGE}\n\
*Report:* <https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/${CIRCLE_NODE_INDEX}/tmp/mochawesome-report/mochawesome.html|View HTML Report>\n\
*Job:* <https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}|View Job>"
SLACK_MESSAGE=":x: *E2E Tests Failed :x:*\n\
*Project:* ${CIRCLE_PROJECT_REPONAME}\n\
*Triggered by:* ${CIRCLE_USERNAME}\n\
*Branch:* ${CIRCLE_BRANCH}\n\
*Commit:* <https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}|${CIRCLE_SHA1}>\n\n\
*Test Summary:*\n\
*Total Suites:* ${TOTAL_SUITES}\n\
*Passes:* ${TOTAL_PASSES}\n\
*Pending:* ${TOTAL_PENDING}\n\
*Failures:* ${TOTAL_FAILURES}\n\
*Start Time:* ${START_TIME_FORMATTED}\n\
*End Time:* ${END_TIME_FORMATTED}\n\
*Duration:* ${DURATION_MIN} minutes\n\n\
*Failed Tests:*\n${MESSAGE}\n\
*Report:* <https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/${CIRCLE_NODE_INDEX}/tmp/mochawesome-report/mochawesome.html|View HTML Report>\n\
*Job:* <https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}|View Job>"
else
SLACK_MESSAGE=":white_check_mark: All E2E tests passed\n\
*Project:* ${CIRCLE_PROJECT_REPONAME}\n\
*Triggered by:* ${CIRCLE_USERNAME}\n\
*Branch:* ${CIRCLE_BRANCH}\n\
*Commit:* <https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}|${CIRCLE_SHA1}>\n\
*Job:* <https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}|View Job>\n\
*Report:* <https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/${CIRCLE_NODE_INDEX}/tmp/mochawesome-report/mochawesome.html|View HTML Report>\n\
\n*Test Summary:*\n\
*Total Suites:* ${TOTAL_SUITES}\n\
*Passes:* ${TOTAL_PASSES}\n\
*Pending:* ${TOTAL_PENDING}\n\
*Failures:* ${TOTAL_FAILURES}\n\
*Start Time:* ${START_TIME_FORMATTED}\n\
*End Time:* ${END_TIME_FORMATTED}\n\
*Duration:* ${DURATION_MIN} minutes"
SLACK_MESSAGE=":white_check_mark: *All E2E tests passed!*\n\
*Project:* ${CIRCLE_PROJECT_REPONAME}\n\
*Triggered by:* ${CIRCLE_USERNAME}\n\
*Branch:* ${CIRCLE_BRANCH}\n\
*Commit:* <https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}|${CIRCLE_SHA1}>\n\
*Job:* <https://circleci.com/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}|View Job>\n\
*Report:* <https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/${CIRCLE_NODE_INDEX}/tmp/mochawesome-report/mochawesome.html|View HTML Report>\n\n\
*Test Summary:*\n\
*Total Suites:* ${TOTAL_SUITES}\n\
*Passes:* ${TOTAL_PASSES}\n\
*Pending:* ${TOTAL_PENDING}\n\
*Failures:* ${TOTAL_FAILURES}\n\
*Start Time:* ${START_TIME_FORMATTED}\n\
*End Time:* ${END_TIME_FORMATTED}\n\
*Duration:* ${DURATION_MIN} minutes"
fi

curl -X POST -H 'Content-type: application/json' --data '{"text":"'"$SLACK_MESSAGE"'"}' $E2E_SLACK_WEBHOOK_URL


publish-npm-package:
working_directory: ~/etherspot-modular-sdk
docker:
- image: cimg/node:20.11.1
auth:
username: $DOCKERHUB_USER
password: $DOCKERHUB_PASSWORD
steps:
- checkout
- run:
name: Install Bun
command: |
curl -fsSL https://bun.sh/install | bash
echo 'export BUN_INSTALL="$HOME/.bun"' >> $BASH_ENV
echo 'export PATH="$BUN_INSTALL/bin:$PATH"' >> $BASH_ENV
source $BASH_ENV
- restore_cache:
key: dependency-cache-{{ checksum "bun.lockb" }}
- run:
name: Authenticate with registry
command: echo "//registry.npmjs.org/:_authToken=$ETHERSPOT_NPM_TOKEN" > ~/etherspot-modular-sdk/.npmrc
- run:
name: Install dependencies
command: bun install
- run:
name: Build Etherspot Modular SDK
command: bun run build
- run:
name: Publish package to npm
command: |
cd ~/etherspot-modular-sdk
bun publish --access public
- run:
name: Announce Publish
command: |
chmod +x .circleci/announcePublish.sh
.circleci/announcePublish.sh "Etherspot Modular SDK" "$(node -e "console.log(require('./package.json').version)")"

publish-github-release:
docker:
- image: ardd97/ghr
steps:
- checkout
- run:
name: Publish Release on GitHub
command: |
PACKAGE_VERSION="$(jq .version package.json -r)"
echo $PACKAGE_VERSION
ghr -t "${GITHUB_TOKEN}" -u "${CIRCLE_PROJECT_USERNAME}" -r "${CIRCLE_PROJECT_REPONAME}" -c "${CIRCLE_SHA1}" "$PACKAGE_VERSION"
Comment on lines +205 to +215
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify Docker image provenance and ghr version stability.

The publish-github-release job uses the Docker image ardd97/ghr, which is not an official repository image. While it may be legitimate, consider:

  1. Verify the image is actively maintained and trustworthy.
  2. Pin to a specific image tag/digest rather than relying on latest (implicit), to ensure reproducible builds and prevent supply-chain surprises if the image is updated.
  3. The ghr tool is invoked without an explicit version check. If the image doesn't specify a pinned version, future runs may pick up breaking changes.

For better security and stability, consider using an official GitHub Actions container or pinning the image to a specific digest.


🏁 Script executed:

#!/bin/bash
# Verify the image exists and check its latest tag info

# Check if the image is publicly available
docker pull ardd97/ghr:latest 2>&1 | head -5

# Attempt to determine the current tag and when it was last updated
curl -s https://hub.docker.com/v2/repositories/ardd97/ghr/tags | jq -r '.results[] | "\(.name) (updated: \(.last_updated))"' | head -10

Length of output: 90


Replace unmaintained Docker image with current, pinned version.

The primary ghr tool is actively maintained (latest v0.17.0, Oct 2024), but the ardd97/ghr image itself is unmaintained since June 2021—over 3 years ago. The implicit latest tag pulls a stale container with outdated dependencies and potential security vulnerabilities.

Recommendations:

  1. Use cibuilds/github instead, a lighter, maintained CircleCI convenience image with ghr pre-installed and pin to a specific version digest
  2. Alternatively, replace the Docker image step with direct Go installation in the run command to fetch the latest ghr binary
  3. Pin both the image tag and ghr version to ensure reproducible, secure builds
🤖 Prompt for AI Agents
In .circleci/config.yml around lines 205 to 215 the job uses the unmaintained
ardd97/ghr Docker image (implicit latest) which is stale and insecure; replace
it with a maintained, pinned image (for example use cibuilds/github with a
specific digest or tagged version) or convert the step to a run step that
installs a specific ghr release (pin the ghr version) at runtime; ensure you
update the docker: image field to the chosen pinned image or add the
installation commands in the publish step, and document the pinned ghr version
so builds remain reproducible.


workflows:
install-and-publish:
jobs:
- install:
context: general-vars
filters:
branches:
only:
- e2e-modular
only: master

- e2e-tests:
name: testnet-e2e-tests
context: general-vars
filters:
branches:
only:
- e2e-modular

only: master

- publish-npm-package:
context: general-vars
requires:
- testnet-e2e-tests
filters:
branches:
only: master

- publish-github-release:
context: general-vars
requires:
- publish-npm-package
filters:
branches:
only: master
Loading