ci.yml 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. # badge: https://github.com/borgbackup/borg/workflows/CI/badge.svg?branch=master
  2. name: CI
  3. on:
  4. push:
  5. branches: [ master ]
  6. tags:
  7. - '2.*'
  8. pull_request:
  9. branches: [ master ]
  10. paths:
  11. - '**.py'
  12. - '**.pyx'
  13. - '**.c'
  14. - '**.h'
  15. - '**.yml'
  16. - '**.toml'
  17. - '**.cfg'
  18. - '**.ini'
  19. - 'requirements.d/*'
  20. - '!docs/**'
  21. jobs:
  22. lint:
  23. runs-on: ubuntu-22.04
  24. timeout-minutes: 5
  25. steps:
  26. - uses: actions/checkout@v4
  27. - uses: chartboost/ruff-action@v1
  28. security:
  29. runs-on: ubuntu-24.04
  30. timeout-minutes: 5
  31. steps:
  32. - uses: actions/checkout@v4
  33. - name: Set up Python
  34. uses: actions/setup-python@v5
  35. with:
  36. python-version: '3.10'
  37. - name: Install dependencies
  38. run: |
  39. python -m pip install --upgrade pip
  40. pip install bandit[toml]
  41. - name: Run Bandit
  42. run: |
  43. bandit -r src/borg -c pyproject.toml
  44. asan_ubsan:
  45. runs-on: ubuntu-24.04
  46. timeout-minutes: 25
  47. needs: [lint, security]
  48. steps:
  49. - uses: actions/checkout@v4
  50. with:
  51. # Just fetching one commit is not enough for setuptools-scm, so we fetch all.
  52. fetch-depth: 0
  53. fetch-tags: true
  54. - name: Set up Python
  55. uses: actions/setup-python@v5
  56. with:
  57. python-version: '3.12'
  58. - name: Install system packages
  59. run: |
  60. sudo apt-get update
  61. sudo apt-get install -y pkg-config build-essential
  62. sudo apt-get install -y libssl-dev libacl1-dev libxxhash-dev liblz4-dev libzstd-dev
  63. - name: Install Python dependencies
  64. run: |
  65. python -m pip install --upgrade pip
  66. pip install -r requirements.d/development.txt
  67. - name: Build Borg with ASan/UBSan
  68. # Build the C/Cython extensions with AddressSanitizer and UndefinedBehaviorSanitizer enabled.
  69. # How this works:
  70. # - The -fsanitize=address,undefined flags inject runtime checks into our native code. If a bug is hit
  71. # (e.g., buffer overflow, use-after-free, out-of-bounds, or undefined behavior), the sanitizer prints
  72. # a detailed error report to stderr, including a stack trace, and forces the process to exit with
  73. # non-zero status. In CI, this will fail the step/job so you will notice.
  74. # - ASAN_OPTIONS/UBSAN_OPTIONS configure the sanitizers' runtime behavior (see below for meanings).
  75. env:
  76. CFLAGS: "-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined"
  77. CXXFLAGS: "-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined"
  78. LDFLAGS: "-fsanitize=address,undefined"
  79. # ASAN_OPTIONS controls AddressSanitizer runtime tweaks:
  80. # - detect_leaks=0: Disable LeakSanitizer to avoid false positives with CPython/pymalloc in short-lived tests.
  81. # - strict_string_checks=1: Make invalid string operations (e.g., over-reads) more likely to be detected.
  82. # - check_initialization_order=1: Catch uses that depend on static initialization order (C++).
  83. # - detect_stack_use_after_return=1: Detect stack-use-after-return via stack poisoning (may increase overhead).
  84. ASAN_OPTIONS: "detect_leaks=0:strict_string_checks=1:check_initialization_order=1:detect_stack_use_after_return=1"
  85. # UBSAN_OPTIONS controls UndefinedBehaviorSanitizer runtime:
  86. # - print_stacktrace=1: Include a stack trace for UB reports to ease debugging.
  87. # Note: UBSan is recoverable by default (process may continue after reporting). If you want CI to
  88. # abort immediately and fail on the first UB, add `halt_on_error=1` (e.g., UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1").
  89. UBSAN_OPTIONS: "print_stacktrace=1"
  90. # PYTHONDEVMODE enables additional Python runtime checks and warnings.
  91. PYTHONDEVMODE: "1"
  92. run: pip install -e .
  93. - name: Run tests under sanitizers
  94. env:
  95. ASAN_OPTIONS: "detect_leaks=0:strict_string_checks=1:check_initialization_order=1:detect_stack_use_after_return=1"
  96. UBSAN_OPTIONS: "print_stacktrace=1"
  97. PYTHONDEVMODE: "1"
  98. # Ensure the ASan runtime is loaded first to avoid "ASan runtime does not come first" warnings.
  99. # We discover libasan/libubsan paths via gcc and preload them for the Python test process.
  100. # the remote tests are slow and likely won't find anything useful
  101. run: |
  102. set -euo pipefail
  103. export LD_PRELOAD="$(gcc -print-file-name=libasan.so):$(gcc -print-file-name=libubsan.so)"
  104. echo "Using LD_PRELOAD=$LD_PRELOAD"
  105. pytest -v --benchmark-skip -k "not remote"
  106. native_tests:
  107. needs: [lint, security]
  108. permissions:
  109. contents: read
  110. id-token: write
  111. attestations: write
  112. strategy:
  113. fail-fast: true
  114. # noinspection YAMLSchemaValidation
  115. matrix: >-
  116. ${{ fromJSON(
  117. github.event_name == 'pull_request' && '{
  118. "include": [
  119. {"os": "ubuntu-22.04", "python-version": "3.10", "toxenv": "mypy"},
  120. {"os": "ubuntu-22.04", "python-version": "3.11", "toxenv": "docs"},
  121. {"os": "ubuntu-22.04", "python-version": "3.10", "toxenv": "py310-llfuse"},
  122. {"os": "ubuntu-24.04", "python-version": "3.14", "toxenv": "py314-mfusepy"}
  123. ]
  124. }' || '{
  125. "include": [
  126. {"os": "ubuntu-22.04", "python-version": "3.10", "toxenv": "mypy"},
  127. {"os": "ubuntu-22.04", "python-version": "3.11", "toxenv": "docs"},
  128. {"os": "ubuntu-22.04", "python-version": "3.10", "toxenv": "py310-llfuse"},
  129. {"os": "ubuntu-22.04", "python-version": "3.11", "toxenv": "py311-llfuse", "binary": "borg-linux-glibc235-x86_64-gh"},
  130. {"os": "ubuntu-22.04-arm", "python-version": "3.11", "toxenv": "py311-llfuse", "binary": "borg-linux-glibc235-arm64-gh"},
  131. {"os": "ubuntu-24.04", "python-version": "3.12", "toxenv": "py312-pyfuse3"},
  132. {"os": "ubuntu-24.04", "python-version": "3.13", "toxenv": "py313-pyfuse3"},
  133. {"os": "ubuntu-24.04", "python-version": "3.14", "toxenv": "py314-mfusepy"},
  134. {"os": "macos-15-intel", "python-version": "3.11", "toxenv": "py311-none", "binary": "borg-macos-15-x86_64-gh"},
  135. {"os": "macos-15", "python-version": "3.11", "toxenv": "py311-none", "binary": "borg-macos-15-arm64-gh"}
  136. ]
  137. }'
  138. ) }}
  139. env:
  140. TOXENV: ${{ matrix.toxenv }}
  141. runs-on: ${{ matrix.os }}
  142. # macOS machines can be slow, if overloaded.
  143. timeout-minutes: 360
  144. steps:
  145. - uses: actions/checkout@v4
  146. with:
  147. # Just fetching one commit is not enough for setuptools-scm, so we fetch all.
  148. fetch-depth: 0
  149. fetch-tags: true
  150. - name: Set up Python ${{ matrix.python-version }}
  151. uses: actions/setup-python@v5
  152. with:
  153. python-version: ${{ matrix.python-version }}
  154. - name: Cache pip
  155. uses: actions/cache@v4
  156. with:
  157. path: ~/.cache/pip
  158. key: ${{ runner.os }}-pip-${{ hashFiles('requirements.d/development.txt') }}
  159. restore-keys: |
  160. ${{ runner.os }}-pip-
  161. ${{ runner.os }}-
  162. - name: Install Linux packages
  163. if: ${{ runner.os == 'Linux' }}
  164. run: |
  165. sudo apt-get update
  166. sudo apt-get install -y pkg-config build-essential
  167. sudo apt-get install -y libssl-dev libacl1-dev libxxhash-dev liblz4-dev libzstd-dev
  168. sudo apt-get install -y bash zsh fish # for shell completion tests
  169. sudo apt-get install -y rclone openssh-server curl
  170. if [[ "$TOXENV" == *"llfuse"* ]]; then
  171. sudo apt-get install -y libfuse-dev fuse # Required for Python llfuse module
  172. elif [[ "$TOXENV" == *"pyfuse3"* || "$TOXENV" == *"mfusepy"* ]]; then
  173. sudo apt-get install -y libfuse3-dev fuse3 # Required for Python pyfuse3 module
  174. fi
  175. - name: Install macOS packages
  176. if: ${{ runner.os == 'macOS' }}
  177. run: |
  178. brew unlink pkg-config@0.29.2 || true
  179. brew bundle install
  180. - name: Configure OpenSSH SFTP server (test only)
  181. if: ${{ runner.os == 'Linux' }}
  182. run: |
  183. sudo mkdir -p /run/sshd
  184. sudo useradd -m -s /bin/bash sftpuser || true
  185. # Create SSH key for the CI user and authorize it for sftpuser
  186. mkdir -p ~/.ssh
  187. chmod 700 ~/.ssh
  188. test -f ~/.ssh/id_ed25519 || ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519
  189. sudo mkdir -p /home/sftpuser/.ssh
  190. sudo chmod 700 /home/sftpuser/.ssh
  191. sudo cp ~/.ssh/id_ed25519.pub /home/sftpuser/.ssh/authorized_keys
  192. sudo chown -R sftpuser:sftpuser /home/sftpuser/.ssh
  193. sudo chmod 600 /home/sftpuser/.ssh/authorized_keys
  194. # Allow publickey auth and enable Subsystem sftp
  195. sudo sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
  196. sudo sed -i 's/^#\?PubkeyAuthentication .*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
  197. if ! grep -q '^Subsystem sftp' /etc/ssh/sshd_config; then echo 'Subsystem sftp /usr/lib/openssh/sftp-server' | sudo tee -a /etc/ssh/sshd_config; fi
  198. # Ensure host keys exist to avoid slow generation on first sshd start
  199. sudo ssh-keygen -A
  200. # Start sshd (listen on default 22 inside runner)
  201. sudo /usr/sbin/sshd -D &
  202. # Add host key to known_hosts so paramiko trusts it
  203. ssh-keyscan -H localhost 127.0.0.1 | tee -a ~/.ssh/known_hosts
  204. # Start ssh-agent and add our key so paramiko can use the agent
  205. eval "$(ssh-agent -s)"
  206. ssh-add ~/.ssh/id_ed25519
  207. # Export SFTP test URL for tox via GITHUB_ENV
  208. echo "BORG_TEST_SFTP_REPO=sftp://sftpuser@localhost:22/borg/sftp-repo" >> $GITHUB_ENV
  209. - name: Install and configure MinIO S3 server (test only)
  210. if: ${{ runner.os == 'Linux' }}
  211. run: |
  212. set -e
  213. arch=$(uname -m)
  214. case "$arch" in
  215. x86_64|amd64) srv_url=https://dl.min.io/server/minio/release/linux-amd64/minio; cli_url=https://dl.min.io/client/mc/release/linux-amd64/mc ;;
  216. aarch64|arm64) srv_url=https://dl.min.io/server/minio/release/linux-arm64/minio; cli_url=https://dl.min.io/client/mc/release/linux-arm64/mc ;;
  217. *) echo "Unsupported arch: $arch"; exit 1 ;;
  218. esac
  219. curl -fsSL -o /usr/local/bin/minio "$srv_url"
  220. curl -fsSL -o /usr/local/bin/mc "$cli_url"
  221. sudo chmod +x /usr/local/bin/minio /usr/local/bin/mc
  222. export PATH=/usr/local/bin:$PATH
  223. # Start MinIO on :9000 with default credentials (minioadmin/minioadmin)
  224. MINIO_DIR="$GITHUB_WORKSPACE/.minio-data"
  225. MINIO_LOG="$GITHUB_WORKSPACE/.minio.log"
  226. mkdir -p "$MINIO_DIR"
  227. nohup minio server "$MINIO_DIR" --address ":9000" >"$MINIO_LOG" 2>&1 &
  228. # Wait for MinIO port to be ready
  229. for i in $(seq 1 60); do (echo > /dev/tcp/127.0.0.1/9000) >/dev/null 2>&1 && break; sleep 1; done
  230. # Configure client and create bucket
  231. mc alias set local http://127.0.0.1:9000 minioadmin minioadmin
  232. mc mb --ignore-existing local/borg
  233. # Export S3 test URL for tox via GITHUB_ENV
  234. echo "BORG_TEST_S3_REPO=s3:minioadmin:minioadmin@http://127.0.0.1:9000/borg/s3-repo" >> $GITHUB_ENV
  235. - name: Install Python requirements
  236. run: |
  237. python -m pip install --upgrade pip setuptools wheel
  238. pip install -r requirements.d/development.txt
  239. - name: Install borgbackup
  240. run: |
  241. if [[ "$TOXENV" == *"llfuse"* ]]; then
  242. pip install -ve ".[llfuse]"
  243. elif [[ "$TOXENV" == *"pyfuse3"* ]]; then
  244. pip install -ve ".[pyfuse3]"
  245. elif [[ "$TOXENV" == *"mfusepy"* ]]; then
  246. pip install -ve ".[mfusepy]"
  247. else
  248. pip install -ve .
  249. fi
  250. - name: Build Borg fat binaries (${{ matrix.binary }})
  251. if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
  252. run: |
  253. pip install 'pyinstaller==6.14.2'
  254. mkdir -p dist/binary
  255. # Ensure locally built binaries in ./dist/binary are found during tox tests
  256. echo "$GITHUB_WORKSPACE/dist/binary" >> "$GITHUB_PATH"
  257. pyinstaller --clean --distpath=dist/binary scripts/borg.exe.spec
  258. - name: Smoke-test the built binary (${{ matrix.binary }})
  259. if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
  260. run: |
  261. pushd dist/binary
  262. echo "single-file binary"
  263. chmod +x borg.exe
  264. ./borg.exe -V
  265. echo "single-directory binary"
  266. chmod +x borg-dir/borg.exe
  267. ./borg-dir/borg.exe -V
  268. tar czf borg.tgz borg-dir
  269. popd
  270. echo "borg.exe binary in PATH"
  271. borg.exe -V
  272. - name: Prepare binaries (${{ matrix.binary }})
  273. if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
  274. run: |
  275. mkdir -p artifacts
  276. if [ -f dist/binary/borg.exe ]; then
  277. cp dist/binary/borg.exe artifacts/${{ matrix.binary }}
  278. fi
  279. if [ -f dist/binary/borg.tgz ]; then
  280. cp dist/binary/borg.tgz artifacts/${{ matrix.binary }}.tgz
  281. fi
  282. echo "binary files"
  283. ls -l artifacts/
  284. - name: Attest binaries provenance (${{ matrix.binary }})
  285. if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
  286. uses: actions/attest-build-provenance@v3
  287. with:
  288. subject-path: 'artifacts/*'
  289. - name: Upload binaries (${{ matrix.binary }})
  290. if: ${{ matrix.binary && startsWith(github.ref, 'refs/tags/') }}
  291. uses: actions/upload-artifact@v4
  292. with:
  293. name: ${{ matrix.binary }}
  294. path: artifacts/*
  295. if-no-files-found: error
  296. - name: run tox env
  297. run: |
  298. # do not use fakeroot, but run as root. avoids the dreaded EISDIR sporadic failures. see #2482.
  299. #sudo -E bash -c "tox -e py"
  300. tox --skip-missing-interpreters
  301. - name: Upload coverage to Codecov
  302. uses: codecov/codecov-action@v4
  303. env:
  304. OS: ${{ runner.os }}
  305. python: ${{ matrix.python-version }}
  306. with:
  307. token: ${{ secrets.CODECOV_TOKEN }}
  308. env_vars: OS, python
  309. vm_tests:
  310. permissions:
  311. contents: read
  312. id-token: write
  313. attestations: write
  314. runs-on: ubuntu-24.04
  315. timeout-minutes: 90
  316. needs: [lint, security]
  317. continue-on-error: true
  318. strategy:
  319. fail-fast: false
  320. matrix:
  321. include:
  322. - os: freebsd
  323. version: '14.3'
  324. display_name: FreeBSD
  325. # Controls binary build and provenance attestation on tags
  326. do_binaries: true
  327. artifact_prefix: borg-freebsd-14-x86_64-gh
  328. - os: netbsd
  329. version: '10.1'
  330. display_name: NetBSD
  331. do_binaries: false
  332. - os: openbsd
  333. version: '7.7'
  334. display_name: OpenBSD
  335. do_binaries: false
  336. - os: haiku
  337. version: 'r1beta5'
  338. display_name: Haiku
  339. do_binaries: false
  340. steps:
  341. - name: Check out repository
  342. uses: actions/checkout@v4
  343. with:
  344. fetch-depth: 0
  345. fetch-tags: true
  346. - name: Test on ${{ matrix.display_name }}
  347. id: cross_os
  348. uses: cross-platform-actions/action@v0.29.0
  349. env:
  350. DO_BINARIES: ${{ matrix.do_binaries }}
  351. with:
  352. operating_system: ${{ matrix.os }}
  353. version: ${{ matrix.version }}
  354. shell: bash
  355. run: |
  356. set -euxo pipefail
  357. case "${{ matrix.os }}" in
  358. freebsd)
  359. export IGNORE_OSVERSION=yes
  360. sudo -E pkg update -f
  361. sudo -E pkg install -y xxhash liblz4 zstd pkgconf
  362. sudo -E pkg install -y fusefs-libs
  363. sudo -E kldload fusefs
  364. sudo -E sysctl vfs.usermount=1
  365. sudo -E chmod 666 /dev/fuse
  366. sudo -E pkg install -y rust
  367. sudo -E pkg install -y gmake
  368. sudo -E pkg install -y git
  369. sudo -E pkg install -y python310 py310-sqlite3
  370. sudo -E pkg install -y python311 py311-sqlite3 py311-pip py311-virtualenv
  371. sudo ln -sf /usr/local/bin/python3.11 /usr/local/bin/python3
  372. sudo ln -sf /usr/local/bin/python3.11 /usr/local/bin/python
  373. sudo ln -sf /usr/local/bin/pip3.11 /usr/local/bin/pip3
  374. sudo ln -sf /usr/local/bin/pip3.11 /usr/local/bin/pip
  375. # required for libsodium/pynacl build
  376. export MAKE=gmake
  377. python -m venv .venv
  378. . .venv/bin/activate
  379. python -V
  380. pip -V
  381. python -m pip install --upgrade pip wheel
  382. pip install -r requirements.d/development.txt
  383. pip install -e ".[mfusepy]"
  384. tox -e py311-mfusepy
  385. if [[ "${{ matrix.do_binaries }}" == "true" && "${{ startsWith(github.ref, 'refs/tags/') }}" == "true" ]]; then
  386. python -m pip install 'pyinstaller==6.14.2'
  387. mkdir -p dist/binary
  388. pyinstaller --clean --distpath=dist/binary scripts/borg.exe.spec
  389. pushd dist/binary
  390. echo "single-file binary"
  391. chmod +x borg.exe
  392. ./borg.exe -V
  393. echo "single-directory binary"
  394. chmod +x borg-dir/borg.exe
  395. ./borg-dir/borg.exe -V
  396. tar czf borg.tgz borg-dir
  397. popd
  398. mkdir -p artifacts
  399. if [ -f dist/binary/borg.exe ]; then
  400. cp -v dist/binary/borg.exe artifacts/${{ matrix.artifact_prefix }}
  401. fi
  402. if [ -f dist/binary/borg.tgz ]; then
  403. cp -v dist/binary/borg.tgz artifacts/${{ matrix.artifact_prefix }}.tgz
  404. fi
  405. fi
  406. ;;
  407. netbsd)
  408. arch="$(uname -m)"
  409. sudo -E mkdir -p /usr/pkg/etc/pkgin
  410. echo "http://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/${arch}/10.1/All" | sudo tee /usr/pkg/etc/pkgin/repositories.conf > /dev/null
  411. sudo -E pkgin update
  412. sudo -E pkgin -y upgrade
  413. sudo -E pkgin -y install zstd lz4 xxhash git
  414. sudo -E pkgin -y install rust
  415. sudo -E pkgin -y install pkg-config
  416. sudo -E pkgin -y install py311-pip py311-virtualenv py311-tox
  417. sudo -E ln -sf /usr/pkg/bin/python3.11 /usr/pkg/bin/python3
  418. sudo -E ln -sf /usr/pkg/bin/pip3.11 /usr/pkg/bin/pip3
  419. sudo -E ln -sf /usr/pkg/bin/virtualenv-3.11 /usr/pkg/bin/virtualenv3
  420. sudo -E ln -sf /usr/pkg/bin/tox-3.11 /usr/pkg/bin/tox3
  421. # Ensure base system admin tools are on PATH for the non-root shell
  422. export PATH="/sbin:/usr/sbin:$PATH"
  423. echo "--- Preparing an extattr-enabled filesystem ---"
  424. # On many NetBSD setups /tmp is tmpfs without extended attributes.
  425. # Create a FFS image with extended attributes enabled and use it for TMPDIR.
  426. VNDDEV="vnd0"
  427. IMGFILE="/tmp/fs.img"
  428. sudo -E dd if=/dev/zero of=${IMGFILE} bs=1m count=1024
  429. sudo -E vndconfig -c "${VNDDEV}" "${IMGFILE}"
  430. sudo -E newfs -O 2ea /dev/r${VNDDEV}a
  431. MNT="/mnt/eafs"
  432. sudo -E mkdir -p ${MNT}
  433. sudo -E mount -t ffs -o extattr /dev/${VNDDEV}a $MNT
  434. export TMPDIR="${MNT}/tmp"
  435. sudo -E mkdir -p ${TMPDIR}
  436. sudo -E chmod 1777 ${TMPDIR}
  437. touch ${TMPDIR}/testfile
  438. lsextattr user ${TMPDIR}/testfile && echo "[xattr] *** xattrs SUPPORTED on ${TMPDIR}! ***"
  439. tox3 -e py311-none
  440. ;;
  441. openbsd)
  442. sudo -E pkg_add xxhash lz4 zstd git
  443. sudo -E pkg_add rust
  444. sudo -E pkg_add openssl%3.4
  445. sudo -E pkg_add py3-pip py3-virtualenv py3-tox
  446. export BORG_OPENSSL_NAME=eopenssl34
  447. tox -e py312-none
  448. ;;
  449. haiku)
  450. pkgman refresh
  451. pkgman install -y git pkgconfig zstd lz4 xxhash
  452. pkgman install -y openssl3
  453. pkgman install -y rust_bin
  454. pkgman install -y python3.10
  455. pkgman install -y cffi
  456. pkgman install -y lz4_devel zstd_devel xxhash_devel openssl3_devel libffi_devel
  457. # there is no pkgman package for tox, so we install it into a venv
  458. python3 -m ensurepip --upgrade
  459. python3 -m pip install --upgrade pip wheel
  460. python3 -m venv .venv
  461. . .venv/bin/activate
  462. export PKG_CONFIG_PATH="/system/develop/lib/pkgconfig:/system/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
  463. export BORG_LIBLZ4_PREFIX=/system/develop
  464. export BORG_LIBZSTD_PREFIX=/system/develop
  465. export BORG_LIBXXHASH_PREFIX=/system/develop
  466. export BORG_OPENSSL_PREFIX=/system/develop
  467. pip install -r requirements.d/development.txt
  468. pip install -e .
  469. # troubles with either tox or pytest xdist, so we run pytest manually:
  470. pytest -v -rs --benchmark-skip -k "not remote and not socket"
  471. ;;
  472. esac
  473. - name: Upload artifacts
  474. if: startsWith(github.ref, 'refs/tags/') && matrix.do_binaries
  475. uses: actions/upload-artifact@v4
  476. with:
  477. name: ${{ matrix.artifact_prefix }}
  478. path: artifacts/*
  479. if-no-files-found: ignore
  480. - name: Attest provenance
  481. if: startsWith(github.ref, 'refs/tags/') && matrix.do_binaries
  482. uses: actions/attest-build-provenance@v3
  483. with:
  484. subject-path: 'artifacts/*'
  485. windows_tests:
  486. if: false # can be used to temporarily disable the build
  487. runs-on: windows-latest
  488. timeout-minutes: 120
  489. needs: native_tests
  490. env:
  491. PY_COLORS: 1
  492. defaults:
  493. run:
  494. shell: msys2 {0}
  495. steps:
  496. - uses: actions/checkout@v4
  497. with:
  498. fetch-depth: 0
  499. - uses: msys2/setup-msys2@v2
  500. with:
  501. msystem: UCRT64
  502. update: true
  503. - name: Install system packages
  504. run: ./scripts/msys2-install-deps development
  505. - name: Build python venv
  506. run: |
  507. # building cffi / argon2-cffi in the venv fails, so we try to use the system packages
  508. python -m venv --system-site-packages env
  509. . env/bin/activate
  510. # python -m pip install --upgrade pip
  511. # pip install --upgrade setuptools build wheel
  512. pip install pyinstaller==6.14.2
  513. - name: Build
  514. run: |
  515. # build borg.exe
  516. . env/bin/activate
  517. pip install -e .
  518. pyinstaller -y scripts/borg.exe.spec
  519. # build sdist and wheel in dist/...
  520. python -m build
  521. - uses: actions/upload-artifact@v4
  522. with:
  523. name: borg-windows
  524. path: dist/borg.exe
  525. - name: Run tests
  526. run: |
  527. ./dist/borg.exe -V
  528. . env/bin/activate
  529. borg -V
  530. python -m pytest -n4 --benchmark-skip -vv -rs -k "not remote"
  531. - name: Upload coverage to Codecov
  532. uses: codecov/codecov-action@v4
  533. env:
  534. OS: ${{ runner.os }}
  535. python: '3.11'
  536. with:
  537. token: ${{ secrets.CODECOV_TOKEN }}
  538. env_vars: OS, python