buildkite-pipeline-in-disk.sh 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #!/usr/bin/env bash
  2. #
  3. # Builds a buildkite pipeline based on the environment variables
  4. #
  5. set -e
  6. cd "$(dirname "$0")"/..
  7. output_file=${1:-/dev/stderr}
  8. if [[ -n $CI_PULL_REQUEST ]]; then
  9. # filter pr number from ci branch.
  10. [[ $CI_BRANCH =~ pull/([0-9]+)/head ]]
  11. pr_number=${BASH_REMATCH[1]}
  12. echo "get affected files from PR: $pr_number"
  13. # get affected files
  14. readarray -t affected_files < <(gh pr diff --name-only "$pr_number")
  15. if [[ ${#affected_files[*]} -eq 0 ]]; then
  16. echo "Unable to determine the files affected by this PR"
  17. exit 1
  18. fi
  19. else
  20. affected_files=()
  21. fi
  22. annotate() {
  23. if [[ -n $BUILDKITE ]]; then
  24. buildkite-agent annotate "$@"
  25. fi
  26. }
  27. # Checks if a CI pull request affects one or more path patterns. Each
  28. # pattern argument is checked in series. If one of them found to be affected,
  29. # return immediately as such.
  30. #
  31. # Bash regular expressions are permitted in the pattern:
  32. # affects .rs$ -- any file or directory ending in .rs
  33. # affects .rs -- also matches foo.rs.bar
  34. # affects ^snap/ -- anything under the snap/ subdirectory
  35. # affects snap/ -- also matches foo/snap/
  36. # Any pattern starting with the ! character will be negated:
  37. # affects !^docs/ -- anything *not* under the docs/ subdirectory
  38. #
  39. affects() {
  40. if [[ -z $CI_PULL_REQUEST ]]; then
  41. # affected_files metadata is not currently available for non-PR builds so assume
  42. # the worse (affected)
  43. return 0
  44. fi
  45. # Assume everything needs to be tested when any Dockerfile changes
  46. for pattern in ^ci/docker-rust/Dockerfile ^ci/docker-rust-nightly/Dockerfile "$@"; do
  47. if [[ ${pattern:0:1} = "!" ]]; then
  48. for file in "${affected_files[@]}"; do
  49. if [[ ! $file =~ ${pattern:1} ]]; then
  50. return 0 # affected
  51. fi
  52. done
  53. else
  54. for file in "${affected_files[@]}"; do
  55. if [[ $file =~ $pattern ]]; then
  56. return 0 # affected
  57. fi
  58. done
  59. fi
  60. done
  61. return 1 # not affected
  62. }
  63. # Checks if a CI pull request affects anything other than the provided path patterns
  64. #
  65. # Syntax is the same as `affects()` except that the negation prefix is not
  66. # supported
  67. #
  68. affects_other_than() {
  69. if [[ -z $CI_PULL_REQUEST ]]; then
  70. # affected_files metadata is not currently available for non-PR builds so assume
  71. # the worse (affected)
  72. return 0
  73. fi
  74. for file in "${affected_files[@]}"; do
  75. declare matched=false
  76. for pattern in "$@"; do
  77. if [[ $file =~ $pattern ]]; then
  78. matched=true
  79. fi
  80. done
  81. if ! $matched; then
  82. return 0 # affected
  83. fi
  84. done
  85. return 1 # not affected
  86. }
  87. start_pipeline() {
  88. echo "# $*" > "$output_file"
  89. echo "steps:" >> "$output_file"
  90. }
  91. command_step() {
  92. cat >> "$output_file" <<EOF
  93. - name: "$1"
  94. command: "$2"
  95. timeout_in_minutes: $3
  96. artifact_paths: "log-*.txt"
  97. EOF
  98. }
  99. trigger_secondary_step() {
  100. cat >> "$output_file" <<"EOF"
  101. - name: "Trigger Build on solana-secondary"
  102. trigger: "solana-secondary"
  103. branches: "!pull/*"
  104. async: true
  105. build:
  106. message: "${BUILDKITE_MESSAGE}"
  107. commit: "${BUILDKITE_COMMIT}"
  108. branch: "${BUILDKITE_BRANCH}"
  109. env:
  110. TRIGGERED_BUILDKITE_TAG: "${BUILDKITE_TAG}"
  111. EOF
  112. }
  113. wait_step() {
  114. echo " - wait" >> "$output_file"
  115. }
  116. all_test_steps() {
  117. command_step checks ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-checks.sh" 20
  118. wait_step
  119. # Coverage...
  120. if affects \
  121. .rs$ \
  122. Cargo.lock$ \
  123. Cargo.toml$ \
  124. ^ci/rust-version.sh \
  125. ^ci/test-coverage.sh \
  126. ^scripts/coverage.sh \
  127. ; then
  128. command_step coverage ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 80
  129. wait_step
  130. else
  131. annotate --style info --context test-coverage \
  132. "Coverage skipped as no .rs files were modified"
  133. fi
  134. # Coverage in disk...
  135. if affects \
  136. .rs$ \
  137. Cargo.lock$ \
  138. Cargo.toml$ \
  139. ^ci/rust-version.sh \
  140. ^ci/test-coverage.sh \
  141. ^scripts/coverage-in-disk.sh \
  142. ; then
  143. command_step coverage-in-disk ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-coverage.sh" 80
  144. wait_step
  145. else
  146. annotate --style info --context test-coverage \
  147. "Coverage skipped as no .rs files were modified"
  148. fi
  149. # Full test suite
  150. .buildkite/scripts/build-stable.sh >> "$output_file"
  151. wait_step
  152. # SBF test suite
  153. if affects \
  154. .rs$ \
  155. Cargo.lock$ \
  156. Cargo.toml$ \
  157. ^ci/rust-version.sh \
  158. ^ci/test-stable-sbf.sh \
  159. ^ci/test-stable.sh \
  160. ^ci/test-local-cluster.sh \
  161. ^core/build.rs \
  162. ^fetch-perf-libs.sh \
  163. ^platform-tools-sdk/ \
  164. ^programs/ \
  165. ^sdk/ \
  166. ; then
  167. cat >> "$output_file" <<"EOF"
  168. - command: "ci/test-stable-sbf.sh"
  169. name: "stable-sbf"
  170. timeout_in_minutes: 35
  171. artifact_paths: "sbf-dumps.tar.bz2"
  172. agents:
  173. queue: "gcp"
  174. EOF
  175. else
  176. annotate --style info \
  177. "Stable-SBF skipped as no relevant files were modified"
  178. fi
  179. # Downstream backwards compatibility
  180. if affects \
  181. .rs$ \
  182. Cargo.lock$ \
  183. Cargo.toml$ \
  184. ^ci/rust-version.sh \
  185. ^ci/test-stable-perf.sh \
  186. ^ci/test-stable.sh \
  187. ^ci/test-local-cluster.sh \
  188. ^core/build.rs \
  189. ^fetch-perf-libs.sh \
  190. ^platform-tools-sdk/ \
  191. ^programs/ \
  192. ^sdk/ \
  193. ^scripts/build-downstream-projects.sh \
  194. ; then
  195. cat >> "$output_file" <<"EOF"
  196. - command: "scripts/build-downstream-projects.sh"
  197. name: "downstream-projects"
  198. timeout_in_minutes: 30
  199. EOF
  200. else
  201. annotate --style info \
  202. "downstream-projects skipped as no relevant files were modified"
  203. fi
  204. # Wasm support
  205. if affects \
  206. ^ci/test-wasm.sh \
  207. ^ci/test-stable.sh \
  208. ^sdk/ \
  209. ; then
  210. command_step wasm ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-wasm.sh" 20
  211. else
  212. annotate --style info \
  213. "wasm skipped as no relevant files were modified"
  214. fi
  215. # Benches...
  216. if affects \
  217. .rs$ \
  218. Cargo.lock$ \
  219. Cargo.toml$ \
  220. ^ci/rust-version.sh \
  221. ^ci/test-coverage.sh \
  222. ^ci/test-bench.sh \
  223. ; then
  224. command_step bench "ci/test-bench.sh" 40
  225. else
  226. annotate --style info --context test-bench \
  227. "Bench skipped as no .rs files were modified"
  228. fi
  229. command_step "local-cluster" \
  230. ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-local-cluster.sh" \
  231. 40
  232. command_step "local-cluster-flakey" \
  233. ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-local-cluster-flakey.sh" \
  234. 10
  235. command_step "local-cluster-slow-1" \
  236. ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-local-cluster-slow-1.sh" \
  237. 40
  238. command_step "local-cluster-slow-2" \
  239. ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_stable_docker_image ci/test-local-cluster-slow-2.sh" \
  240. 40
  241. }
  242. pull_or_push_steps() {
  243. command_step sanity "ci/test-sanity.sh" 5
  244. wait_step
  245. # Check for any .sh file changes
  246. if affects .sh$; then
  247. command_step shellcheck "ci/shellcheck.sh" 5
  248. wait_step
  249. fi
  250. # Run the full test suite by default, skipping only if modifications are local
  251. # to some particular areas of the tree
  252. if affects_other_than ^.buildkite ^.mergify .md$ ^docs/ ^.gitbook; then
  253. all_test_steps
  254. fi
  255. # docs changes run on Github actions...
  256. }
  257. if [[ -n $BUILDKITE_TAG ]]; then
  258. start_pipeline "Tag pipeline for $BUILDKITE_TAG"
  259. annotate --style info --context release-tag \
  260. "https://github.com/anza-xyz/agave/releases/$BUILDKITE_TAG"
  261. # Jump directly to the secondary build to publish release artifacts quickly
  262. trigger_secondary_step
  263. exit 0
  264. fi
  265. if [[ $BUILDKITE_BRANCH =~ ^pull ]]; then
  266. echo "+++ Affected files in this PR"
  267. for file in "${affected_files[@]}"; do
  268. echo "- $file"
  269. done
  270. start_pipeline "Pull request pipeline for $BUILDKITE_BRANCH"
  271. # Add helpful link back to the corresponding Github Pull Request
  272. annotate --style info --context pr-backlink \
  273. "Github Pull Request: https://github.com/anza-xyz/agave/$BUILDKITE_BRANCH"
  274. pull_or_push_steps
  275. exit 0
  276. fi
  277. start_pipeline "Push pipeline for ${BUILDKITE_BRANCH:-?unknown branch?}"
  278. pull_or_push_steps
  279. wait_step
  280. trigger_secondary_step
  281. exit 0