# unittests using the 'latest' runtime python-dependencies task: container: image: $ELECTRUM_IMAGE cpu: 1 memory: 2G matrix: - name: "unittests: py$ELECTRUM_PYTHON_VERSION" env: ELECTRUM_IMAGE: python:$ELECTRUM_PYTHON_VERSION matrix: - env: ELECTRUM_PYTHON_VERSION: 3.10 - env: ELECTRUM_PYTHON_VERSION: 3.11 - env: ELECTRUM_PYTHON_VERSION: 3.12 - env: ELECTRUM_PYTHON_VERSION: 3.13 - env: ELECTRUM_PYTHON_VERSION: 3.14 - name: "unittests: py3.14, debug-mode" env: ELECTRUM_PYTHON_VERSION: 3.14 # enable additional checks: PYTHONASYNCIODEBUG: "1" PYTHONDEVMODE: "1" pip_cache: folder: ~/.cache/pip fingerprint_script: echo $ELECTRUM_IMAGE && cat $ELECTRUM_REQUIREMENTS_CI && cat $ELECTRUM_REQUIREMENTS tag_script: - git tag libsecp_build_cache: folder: contrib/_saved_secp256k1_build fingerprint_script: sha256sum ./contrib/make_libsecp256k1.sh populate_script: - apt-get update - apt-get -y install automake libtool - ./contrib/make_libsecp256k1.sh - mkdir contrib/_saved_secp256k1_build - cp electrum/libsecp256k1.so.* contrib/_saved_secp256k1_build/ install_script: - apt-get update # qml test reqs: - apt-get -y install libgl1 libegl1 libxkbcommon0 libdbus-1-3 - pip install -r $ELECTRUM_REQUIREMENTS_CI # electrum itself: - export ELECTRUM_ECC_DONT_COMPILE=1 - pip install ".[tests,qml_gui]" version_script: - python3 --version - pip freeze --all pytest_script: - > coverage run --source=electrum \ "--omit=electrum/gui/*,electrum/plugins/*,electrum/scripts/*" \ -m pytest tests -v - coverage report coveralls_script: - if [ ! -z "$COVERALLS_REPO_TOKEN" ] && [ "$ELECTRUM_PYTHON_VERSION" = "3.10" ] ; then coveralls ; fi env: LD_LIBRARY_PATH: contrib/_saved_secp256k1_build/ ELECTRUM_REQUIREMENTS_CI: contrib/requirements/requirements-ci.txt ELECTRUM_REQUIREMENTS: contrib/requirements/requirements.txt # following CI_* env vars are set up for coveralls CI_NAME: "CirrusCI" CI_BUILD_NUMBER: $CIRRUS_BUILD_ID CI_JOB_ID: $CIRRUS_TASK_ID CI_BUILD_URL: "https://cirrus-ci.com/task/$CIRRUS_TASK_ID" CI_BRANCH: $CIRRUS_BRANCH CI_PULL_REQUEST: $CIRRUS_PR # in addition, COVERALLS_REPO_TOKEN is set as an "override" in https://cirrus-ci.com/settings/... depends_on: - "linter: Flake8 Mandatory" # unittests using the ~same frozen dependencies that are used in the released binaries # note: not using pinned pyqt here, due to "qml_gui" extra task: container: image: $ELECTRUM_IMAGE cpu: 1 memory: 2G name: "unittests: py3.10, frozen-deps" pip_cache: folder: ~/.cache/pip fingerprint_script: echo $ELECTRUM_IMAGE && cat contrib/requirements/requirements*.txt && cat contrib/deterministic-build/requirements*.txt tag_script: - git tag libsecp_build_cache: folder: contrib/_saved_secp256k1_build fingerprint_script: sha256sum ./contrib/make_libsecp256k1.sh populate_script: - apt-get update - apt-get -y install automake libtool - ./contrib/make_libsecp256k1.sh - mkdir contrib/_saved_secp256k1_build - cp electrum/libsecp256k1.so.* contrib/_saved_secp256k1_build/ install_script: - apt-get update # qml test reqs: - apt-get -y install libgl1 libegl1 libxkbcommon0 libdbus-1-3 - pip install -r contrib/deterministic-build/requirements-build-base.txt - pip install -r contrib/requirements/requirements-ci.txt # electrum itself: - export ELECTRUM_ECC_DONT_COMPILE=1 - pip install -r contrib/deterministic-build/requirements.txt -r contrib/deterministic-build/requirements-binaries.txt - pip install ".[tests,qml_gui]" version_script: - python3 --version - pip freeze --all pytest_script: - pytest tests -v env: ELECTRUM_IMAGE: python:3.10 LD_LIBRARY_PATH: contrib/_saved_secp256k1_build/ depends_on: - "linter: Flake8 Mandatory" task: name: "locale: upload to crowdin" container: image: $ELECTRUM_IMAGE cpu: 1 memory: 1G pip_cache: folder: ~/.cache/pip fingerprint_script: echo Locale && echo $ELECTRUM_IMAGE && cat $ELECTRUM_REQUIREMENTS_CI install_script: - apt-get update - apt-get -y install gettext qt6-l10n-tools - pip install -r $ELECTRUM_REQUIREMENTS_CI - pip install requests submodules_script: - git submodule update --init locale_script: - contrib/locale/push_locale.py env: ELECTRUM_IMAGE: python:3.10 ELECTRUM_REQUIREMENTS_CI: contrib/requirements/requirements-ci.txt # in addition, crowdin_api_key is set as an "override" in https://cirrus-ci.com/settings/... depends_on: - "unittests: py3.10" only_if: $CIRRUS_BRANCH == 'master' task: name: "Regtest functional tests" compute_engine_instance: image_project: cirrus-images image: family/docker-builder platform: linux cpu: 1 memory: 1G pip_cache: folder: ~/.cache/pip fingerprint_script: echo Regtest && echo docker_builder && cat $ELECTRUM_REQUIREMENTS bitcoind_cache: folder: /tmp/bitcoind populate_script: mkdir -p /tmp/bitcoind install_script: - apt-get update - apt-get -y install curl jq bc - python3 -m pip install --user --upgrade pip # install electrum - export ELECTRUM_ECC_DONT_COMPILE=1 # we build manually to make caching it easier - python3 -m pip install .[tests] --ignore-installed # ignore installed system installed attrs # install e-x some commits after 1.18.0 tag - python3 -m pip install git+https://github.com/spesmilo/electrumx.git@0b260d4345242cc41e316e97d7de10ae472fd172 - "BITCOIND_VERSION=$(curl https://bitcoincore.org/en/download/ | grep -E -i --only-matching 'Latest version: [0-9\\.]+' | grep -E --only-matching '[0-9\\.]+')" - BITCOIND_FILENAME=bitcoin-$BITCOIND_VERSION-x86_64-linux-gnu.tar.gz - BITCOIND_PATH=/tmp/bitcoind/$BITCOIND_FILENAME - BITCOIND_URL=https://bitcoincore.org/bin/bitcoin-core-$BITCOIND_VERSION/$BITCOIND_FILENAME - tar -xaf $BITCOIND_PATH || (rm -f /tmp/bitcoind/* && curl --output $BITCOIND_PATH $BITCOIND_URL && tar -xaf $BITCOIND_PATH) - cp -a bitcoin-$BITCOIND_VERSION/* /usr/ libsecp_build_cache: folder: contrib/_saved_secp256k1_build fingerprint_script: sha256sum ./contrib/make_libsecp256k1.sh populate_script: - apt-get -y install automake libtool - ./contrib/make_libsecp256k1.sh - mkdir contrib/_saved_secp256k1_build - cp electrum/libsecp256k1.so.* contrib/_saved_secp256k1_build/ bitcoind_service_background_script: - tests/regtest/run_bitcoind.sh electrumx_service_background_script: - tests/regtest/run_electrumx.sh # if any test fails, the test will get aborted (--failfast) and the wallet directories will be # available for download in the Cirrus UI regtest_script: - sleep 10s - python3 -m unittest tests/regtest.py --failfast || TEST_EXIT_CODE=$? - tar -czf test_wallets.tar.gz /tmp/alice /tmp/bob /tmp/carol || true - exit ${TEST_EXIT_CODE:-0} on_failure: wallet_artifacts: path: "test_wallets.tar.gz" env: LD_LIBRARY_PATH: contrib/_saved_secp256k1_build/ ELECTRUM_REQUIREMENTS: contrib/requirements/requirements.txt PIP_BREAK_SYSTEM_PACKAGES: 1 # ElectrumX exits with an error without this: ALLOW_ROOT: 1 depends_on: - "linter: Flake8 Mandatory" task: container: image: $ELECTRUM_IMAGE cpu: 1 memory: 1G pip_cache: folder: ~/.cache/pip fingerprint_script: echo Flake8 && echo $ELECTRUM_IMAGE && cat $ELECTRUM_REQUIREMENTS install_script: - pip install "flake8==7.3.0" "flake8-bugbear==25.10.21" flake8_script: - flake8 . --count --select="$ELECTRUM_LINTERS" --ignore="$ELECTRUM_LINTERS_IGNORE" --show-source --statistics --exclude "*_pb2.py,electrum/_vendor/" env: ELECTRUM_IMAGE: python:3.10 ELECTRUM_REQUIREMENTS: contrib/requirements/requirements.txt matrix: - name: "linter: Flake8 Mandatory" env: # list of error codes: # - https://flake8.pycqa.org/en/latest/user/error-codes.html # - https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes # - https://github.com/PyCQA/flake8-bugbear/tree/8c0e7eb04217494d48d0ab093bf5b31db0921989#list-of-warnings ELECTRUM_LINTERS: E9,E101,E129,E273,E274,E703,E71,E722,F5,F6,F7,F8,W191,W29,B,B909 ELECTRUM_LINTERS_IGNORE: B007,B009,B010,B036,B042,F541,F841 - name: "linter: Flake8 Non-Mandatory" env: ELECTRUM_LINTERS: E,F,W,C90,B ELECTRUM_LINTERS_IGNORE: "" allow_failures: true task: name: "linter: ban unicode" container: image: python:3.10 cpu: 1 memory: 1G main_script: - contrib/ban_unicode.py # Cron jobs configured in https://cirrus-ci.com/settings/... # - job "nightly" on branch "master" at "0 30 2 * * ?" (every day at 02:30Z) task: name: "build: Windows" matrix: - trigger_type: manual only_if: $CIRRUS_CRON == "" - trigger_type: automatic only_if: $CIRRUS_CRON == "nightly" container: dockerfile: contrib/build-wine/Dockerfile cpu: 1 memory: 3G pip_cache: folders: - contrib/build-wine/.cache/win*/wine_pip_cache fingerprint_script: - echo $CIRRUS_TASK_NAME - git ls-files -s contrib/deterministic-build/*.txt - git ls-files -s contrib/build-wine/ build2_cache: folders: - contrib/build-wine/.cache/win*/build fingerprint_script: - echo $CIRRUS_TASK_NAME - cat contrib/make_libsecp256k1.sh | sha256sum - cat contrib/make_libusb.sh | sha256sum - cat contrib/make_zbar.sh | sha256sum - git ls-files -s contrib/build-wine/ build_script: - cd contrib/build-wine - ./make_win.sh binaries_artifacts: path: "contrib/build-wine/dist/*" env: CIRRUS_WORKING_DIR: /opt/wine64/drive_c/electrum CIRRUS_DOCKER_CONTEXT: contrib/build-wine depends_on: - "unittests: py3.10" task: name: "build: Android (QML $APK_ARCH)" matrix: - trigger_type: manual only_if: $CIRRUS_CRON == "" - trigger_type: automatic only_if: $CIRRUS_CRON == "nightly" timeout_in: 90m container: dockerfile: contrib/android/Dockerfile cpu: 8 memory: 24G env: APK_ARCH: arm64-v8a packages_tld_folder_cache: folder: packages fingerprint_script: - echo $CIRRUS_TASK_NAME && cat contrib/deterministic-build/requirements.txt && cat contrib/make_packages.sh - git ls-files -s contrib/android/ p4a_cache: folders: - ".buildozer/android/platform/build-$APK_ARCH/packages" - ".buildozer/android/platform/build-$APK_ARCH/build" fingerprint_script: # note: should *at least* depend on Dockerfile and p4a_recipes/, but contrib/android/ is simplest - git ls-files -s contrib/android/ - echo "qml $APK_ARCH" build_script: - ./contrib/android/make_apk.sh qml "$APK_ARCH" debug binaries_artifacts: path: "dist/*" depends_on: - "unittests: py3.10" ## mac build disabled, as Cirrus CI no longer supports Intel-based mac builds #task: # name: "build: macOS" # macos_instance: # image: catalina-xcode-11.3.1 # env: # TARGET_OS: macOS # pip_cache: # folder: ~/Library/Caches/pip # fingerprint_script: # - echo $CIRRUS_TASK_NAME # - git ls-files -s contrib/deterministic-build/*.txt # - git ls-files -s contrib/osx/ # build2_cache: # folder: contrib/osx/.cache # fingerprint_script: # - echo $CIRRUS_TASK_NAME # - cat contrib/make_libsecp256k1.sh | shasum -a 256 # - cat contrib/make_libusb.sh | shasum -a 256 # - cat contrib/make_zbar.sh | shasum -a 256 # - git ls-files -s contrib/osx/ # install_script: # - git fetch --all --tags # build_script: # - ./contrib/osx/make_osx.sh # sum_script: # - ls -lah dist # - shasum -a 256 dist/*.dmg # binaries_artifacts: # path: "dist/*" task: name: "build: AppImage" matrix: - trigger_type: manual only_if: $CIRRUS_CRON == "" - trigger_type: automatic only_if: $CIRRUS_CRON == "nightly" compute_engine_instance: image_project: cirrus-images image: family/docker-builder platform: linux cpu: 2 memory: 2G pip_cache: folder: contrib/build-linux/appimage/.cache/pip_cache fingerprint_script: - echo $CIRRUS_TASK_NAME - git ls-files -s contrib/deterministic-build/*.txt - git ls-files -s contrib/build-linux/appimage/ build2_cache: folder: contrib/build-linux/appimage/.cache/appimage fingerprint_script: - echo $CIRRUS_TASK_NAME - cat contrib/make_libsecp256k1.sh | sha256sum - git ls-files -s contrib/build-linux/appimage/ build_script: - ./contrib/build-linux/appimage/build.sh binaries_artifacts: path: "dist/*" depends_on: - "unittests: py3.10" task: container: dockerfile: contrib/build-linux/sdist/Dockerfile cpu: 1 memory: 1G pip_cache: folder: ~/.cache/pip fingerprint_script: - echo $CIRRUS_TASK_NAME - git ls-files -s contrib/deterministic-build/*.txt - git ls-files -s contrib/build-linux/sdist/ build_script: - ./contrib/build-linux/sdist/make_sdist.sh binaries_artifacts: path: "dist/*" matrix: - name: "build: tarball" - name: "build: source-only tarball" env: OMIT_UNCLEAN_FILES: 1 depends_on: - "unittests: py3.10" task: name: "check submodules" container: image: python:3.10 cpu: 1 memory: 1G fetch_script: - git fetch --all --tags check_script: - ./contrib/deterministic-build/check_submodules.sh only_if: $CIRRUS_TAG != ''