.travis.yml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. # Environment variables
  2. env:
  3. global:
  4. - CFLAGS=-Werror
  5. - MAKEFLAGS=-j
  6. # Common test script
  7. script:
  8. # make sure example can at least compile
  9. - sed -n '/``` c/,/```/{/```/d; p;}' README.md > test.c &&
  10. make all CFLAGS+="
  11. -Duser_provided_block_device_read=NULL
  12. -Duser_provided_block_device_prog=NULL
  13. -Duser_provided_block_device_erase=NULL
  14. -Duser_provided_block_device_sync=NULL
  15. -include stdio.h"
  16. # run tests
  17. - make clean test TFLAGS+="-nrk"
  18. # common real-life geometries
  19. # NOR flash: read/prog = 1 block = 4KiB
  20. - make clean test TFLAGS+="-nrk -DLFS_READ_SIZE=1 -DLFS_BLOCK_SIZE=4096"
  21. # SD card: read/prog = 512 block = 512
  22. - make clean test TFLAGS+="-nrk -DLFS_READ_SIZE=512 -DLFS_BLOCK_SIZE=512"
  23. # NAND flash: read/prog = 4KiB block = 32KiB
  24. - make clean test TFLAGS+="-nrk -DLFS_READ_SIZE=4096 -DLFS_BLOCK_SIZE=\(32*1024\)"
  25. # other extreme geometries for corner cases
  26. - make clean test TFLAGS+="-nrk -DLFS_NO_INTRINSICS"
  27. - make clean test TFLAGS+="-nrk -DLFS_INLINE_MAX=0"
  28. - make clean test TFLAGS+="-nrk -DLFS_READ_SIZE=1 -DLFS_CACHE_SIZE=1"
  29. - make clean test TFLAGS+="-nrk -DLFS_BLOCK_CYCLES=1"
  30. - make clean test TFLAGS+="-nrk -DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD_SIZE=256"
  31. - make clean test TFLAGS+="-nrk -DLFS_READ_SIZE=11 -DLFS_BLOCK_SIZE=704"
  32. # compile and find the code size with the smallest configuration
  33. - make clean size
  34. OBJ="$(ls lfs*.c | sed 's/\.c/\.o/' | tr '\n' ' ')"
  35. CFLAGS+="-DLFS_NO_ASSERT -DLFS_NO_DEBUG -DLFS_NO_WARN -DLFS_NO_ERROR"
  36. | tee sizes
  37. # update status if we succeeded, compare with master if possible
  38. - |
  39. if [ "$TRAVIS_TEST_RESULT" -eq 0 ]
  40. then
  41. CURR=$(tail -n1 sizes | awk '{print $1}')
  42. PREV=$(curl -u "$GEKY_BOT_STATUSES" https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \
  43. | jq -re "select(.sha != \"$TRAVIS_COMMIT\")
  44. | .statuses[] | select(.context == \"$STAGE/$NAME\").description
  45. | capture(\"code size is (?<size>[0-9]+)\").size" \
  46. || echo 0)
  47. STATUS="Passed, code size is ${CURR}B"
  48. if [ "$PREV" -ne 0 ]
  49. then
  50. STATUS="$STATUS ($(python -c "print '%+.2f' % (100*($CURR-$PREV)/$PREV.0)")%)"
  51. fi
  52. fi
  53. # CI matrix
  54. jobs:
  55. include:
  56. # native testing
  57. - stage: test
  58. env:
  59. - STAGE=test
  60. - NAME=littlefs-x86
  61. # cross-compile with ARM (thumb mode)
  62. - stage: test
  63. env:
  64. - STAGE=test
  65. - NAME=littlefs-arm
  66. - CC="arm-linux-gnueabi-gcc --static -mthumb"
  67. - TFLAGS="-e qemu-arm"
  68. install:
  69. - sudo apt-get install
  70. gcc-arm-linux-gnueabi
  71. libc6-dev-armel-cross
  72. qemu-user
  73. - arm-linux-gnueabi-gcc --version
  74. - qemu-arm -version
  75. # cross-compile with PowerPC
  76. - stage: test
  77. env:
  78. - STAGE=test
  79. - NAME=littlefs-powerpc
  80. - CC="powerpc-linux-gnu-gcc --static"
  81. - TFLAGS="-e qemu-ppc"
  82. install:
  83. - sudo apt-get install
  84. gcc-powerpc-linux-gnu
  85. libc6-dev-powerpc-cross
  86. qemu-user
  87. - powerpc-linux-gnu-gcc --version
  88. - qemu-ppc -version
  89. # cross-compile with MIPS
  90. - stage: test
  91. env:
  92. - STAGE=test
  93. - NAME=littlefs-mips
  94. - CC="mips-linux-gnu-gcc --static"
  95. - TFLAGS="-e qemu-mips"
  96. install:
  97. - sudo apt-get install
  98. gcc-mips-linux-gnu
  99. libc6-dev-mips-cross
  100. qemu-user
  101. - mips-linux-gnu-gcc --version
  102. - qemu-mips -version
  103. # test under valgrind, checking for memory errors
  104. - stage: test
  105. env:
  106. - STAGE=test
  107. - NAME=littlefs-valgrind
  108. - TFLAGS="--valgrind"
  109. install:
  110. - sudo apt-get install valgrind
  111. - valgrind --version
  112. # self-host with littlefs-fuse for fuzz test
  113. - stage: test
  114. env:
  115. - STAGE=test
  116. - NAME=littlefs-fuse
  117. if: branch !~ -prefix$
  118. install:
  119. - sudo apt-get install libfuse-dev
  120. - git clone --depth 1 https://github.com/geky/littlefs-fuse -b v2
  121. - fusermount -V
  122. - gcc --version
  123. before_script:
  124. # setup disk for littlefs-fuse
  125. - rm -rf littlefs-fuse/littlefs/*
  126. - cp -r $(git ls-tree --name-only HEAD) littlefs-fuse/littlefs
  127. - mkdir mount
  128. - sudo chmod a+rw /dev/loop0
  129. - dd if=/dev/zero bs=512 count=4096 of=disk
  130. - losetup /dev/loop0 disk
  131. script:
  132. # self-host test
  133. - make -C littlefs-fuse
  134. - littlefs-fuse/lfs --format /dev/loop0
  135. - littlefs-fuse/lfs /dev/loop0 mount
  136. - ls mount
  137. - mkdir mount/littlefs
  138. - cp -r $(git ls-tree --name-only HEAD) mount/littlefs
  139. - cd mount/littlefs
  140. - stat .
  141. - ls -flh
  142. - make -B test_dirs test_files QUIET=1
  143. # self-host with littlefs-fuse for fuzz test
  144. - stage: test
  145. env:
  146. - STAGE=test
  147. - NAME=littlefs-migration
  148. if: branch !~ -prefix$
  149. install:
  150. - sudo apt-get install libfuse-dev
  151. - git clone --depth 1 https://github.com/geky/littlefs-fuse -b v2 v2
  152. - git clone --depth 1 https://github.com/geky/littlefs-fuse -b v1 v1
  153. - fusermount -V
  154. - gcc --version
  155. before_script:
  156. # setup disk for littlefs-fuse
  157. - rm -rf v2/littlefs/*
  158. - cp -r $(git ls-tree --name-only HEAD) v2/littlefs
  159. - mkdir mount
  160. - sudo chmod a+rw /dev/loop0
  161. - dd if=/dev/zero bs=512 count=4096 of=disk
  162. - losetup /dev/loop0 disk
  163. script:
  164. # compile v1 and v2
  165. - make -C v1
  166. - make -C v2
  167. # run self-host test with v1
  168. - v1/lfs --format /dev/loop0
  169. - v1/lfs /dev/loop0 mount
  170. - ls mount
  171. - mkdir mount/littlefs
  172. - cp -r $(git ls-tree --name-only HEAD) mount/littlefs
  173. - cd mount/littlefs
  174. - stat .
  175. - ls -flh
  176. - make -B test_dirs test_files QUIET=1
  177. # attempt to migrate
  178. - cd ../..
  179. - fusermount -u mount
  180. - v2/lfs --migrate /dev/loop0
  181. - v2/lfs /dev/loop0 mount
  182. # run self-host test with v2 right where we left off
  183. - ls mount
  184. - cd mount/littlefs
  185. - stat .
  186. - ls -flh
  187. - make -B test_dirs test_files QUIET=1
  188. # Automatically create releases
  189. - stage: deploy
  190. env:
  191. - STAGE=deploy
  192. - NAME=deploy
  193. script:
  194. - |
  195. bash << 'SCRIPT'
  196. set -ev
  197. # Find version defined in lfs.h
  198. LFS_VERSION=$(grep -ox '#define LFS_VERSION .*' lfs.h | cut -d ' ' -f3)
  199. LFS_VERSION_MAJOR=$((0xffff & ($LFS_VERSION >> 16)))
  200. LFS_VERSION_MINOR=$((0xffff & ($LFS_VERSION >> 0)))
  201. # Grab latests patch from repo tags, default to 0, needs finagling
  202. # to get past github's pagination api
  203. PREV_URL=https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR.
  204. PREV_URL=$(curl -u "$GEKY_BOT_RELEASES" "$PREV_URL" -I \
  205. | sed -n '/^Link/{s/.*<\(.*\)>; rel="last"/\1/;p;q0};$q1' \
  206. || echo $PREV_URL)
  207. LFS_VERSION_PATCH=$(curl -u "$GEKY_BOT_RELEASES" "$PREV_URL" \
  208. | jq 'map(.ref | match("\\bv.*\\..*\\.(.*)$";"g")
  209. .captures[].string | tonumber) | max + 1' \
  210. || echo 0)
  211. # We have our new version
  212. LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR.$LFS_VERSION_PATCH"
  213. echo "VERSION $LFS_VERSION"
  214. # Check that we're the most recent commit
  215. CURRENT_COMMIT=$(curl -f -u "$GEKY_BOT_RELEASES" \
  216. https://api.github.com/repos/$TRAVIS_REPO_SLUG/commits/master \
  217. | jq -re '.sha')
  218. [ "$TRAVIS_COMMIT" == "$CURRENT_COMMIT" ] || exit 0
  219. # Create major branch
  220. git branch v$LFS_VERSION_MAJOR HEAD
  221. # Create major prefix branch
  222. git config user.name "geky bot"
  223. git config user.email "bot@geky.net"
  224. git fetch https://github.com/$TRAVIS_REPO_SLUG.git \
  225. --depth=50 v$LFS_VERSION_MAJOR-prefix || true
  226. ./scripts/prefix.py lfs$LFS_VERSION_MAJOR
  227. git branch v$LFS_VERSION_MAJOR-prefix $( \
  228. git commit-tree $(git write-tree) \
  229. $(git rev-parse --verify -q FETCH_HEAD | sed -e 's/^/-p /') \
  230. -p HEAD \
  231. -m "Generated v$LFS_VERSION_MAJOR prefixes")
  232. git reset --hard
  233. # Update major version branches (vN and vN-prefix)
  234. git push --atomic https://$GEKY_BOT_RELEASES@github.com/$TRAVIS_REPO_SLUG.git \
  235. v$LFS_VERSION_MAJOR \
  236. v$LFS_VERSION_MAJOR-prefix
  237. # Build release notes
  238. PREV=$(git tag --sort=-v:refname -l "v*" | head -1)
  239. if [ ! -z "$PREV" ]
  240. then
  241. echo "PREV $PREV"
  242. CHANGES=$(git log --oneline $PREV.. --grep='^Merge' --invert-grep)
  243. printf "CHANGES\n%s\n\n" "$CHANGES"
  244. fi
  245. case ${GEKY_BOT_DRAFT:-minor} in
  246. true) DRAFT=true ;;
  247. minor) DRAFT=$(jq -R 'endswith(".0")' <<< "$LFS_VERSION") ;;
  248. false) DRAFT=false ;;
  249. esac
  250. # Create the release and patch version tag (vN.N.N)
  251. curl -f -u "$GEKY_BOT_RELEASES" -X POST \
  252. https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases \
  253. -d "{
  254. \"tag_name\": \"$LFS_VERSION\",
  255. \"name\": \"${LFS_VERSION%.0}\",
  256. \"target_commitish\": \"$TRAVIS_COMMIT\",
  257. \"draft\": $DRAFT,
  258. \"body\": $(jq -sR '.' <<< "$CHANGES")
  259. }" #"
  260. SCRIPT
  261. # Manage statuses
  262. before_install:
  263. - |
  264. curl -u "$GEKY_BOT_STATUSES" -X POST \
  265. https://api.github.com/repos/$TRAVIS_REPO_SLUG/statuses/${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT} \
  266. -d "{
  267. \"context\": \"$STAGE/$NAME\",
  268. \"state\": \"pending\",
  269. \"description\": \"${STATUS:-In progress}\",
  270. \"target_url\": \"https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$TRAVIS_JOB_ID\"
  271. }"
  272. - sudo apt-get install python3-pip
  273. - sudo pip3 install toml
  274. after_failure:
  275. - |
  276. curl -u "$GEKY_BOT_STATUSES" -X POST \
  277. https://api.github.com/repos/$TRAVIS_REPO_SLUG/statuses/${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT} \
  278. -d "{
  279. \"context\": \"$STAGE/$NAME\",
  280. \"state\": \"failure\",
  281. \"description\": \"${STATUS:-Failed}\",
  282. \"target_url\": \"https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$TRAVIS_JOB_ID\"
  283. }"
  284. after_success:
  285. - |
  286. curl -u "$GEKY_BOT_STATUSES" -X POST \
  287. https://api.github.com/repos/$TRAVIS_REPO_SLUG/statuses/${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT} \
  288. -d "{
  289. \"context\": \"$STAGE/$NAME\",
  290. \"state\": \"success\",
  291. \"description\": \"${STATUS:-Passed}\",
  292. \"target_url\": \"https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$TRAVIS_JOB_ID\"
  293. }"
  294. # Job control
  295. stages:
  296. - name: test
  297. - name: deploy
  298. if: branch = master AND type = push