.gitlab-ci.yml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. stages:
  2. - test
  3. - deploy
  4. - container-build
  5. - container-mirror
  6. variables:
  7. DEBIAN_FRONTEND: noninteractive
  8. DEBIAN_OLD_STABLE: buster
  9. DEBIAN_STABLE: bullseye
  10. REPRODUCIBLE_FLAGS: -trimpath -ldflags=-buildid=
  11. # set up apt for automated use
  12. .apt-template: &apt-template
  13. - export LC_ALL=C.UTF-8
  14. - export DEBIAN_FRONTEND=noninteractive
  15. - ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
  16. - echo 'quiet "1";'
  17. 'APT::Install-Recommends "0";'
  18. 'APT::Install-Suggests "0";'
  19. 'APT::Acquire::Retries "20";'
  20. 'APT::Get::Assume-Yes "true";'
  21. 'Dpkg::Use-Pty "0";'
  22. > /etc/apt/apt.conf.d/99gitlab
  23. - apt-get update
  24. - apt-get dist-upgrade
  25. # Set things up to use the OS-native packages for Go. Anything that
  26. # is downloaded by go during the `go fmt` stage is not coming from the
  27. # Debian/Ubuntu repo. So those would need to be packaged for this to
  28. # make it into Debian and/or Ubuntu.
  29. .debian-native-template: &debian-native-template
  30. variables:
  31. GOPATH: /usr/share/gocode
  32. before_script:
  33. - apt-get update
  34. - apt-get -qy install --no-install-recommends
  35. build-essential
  36. ca-certificates
  37. git
  38. golang
  39. golang-github-cheekybits-genny-dev
  40. golang-github-jtolds-gls-dev
  41. golang-github-klauspost-reedsolomon-dev
  42. golang-github-lucas-clemente-quic-go-dev
  43. golang-github-smartystreets-assertions-dev
  44. golang-github-smartystreets-goconvey-dev
  45. golang-github-tjfoc-gmsm-dev
  46. golang-github-xtaci-kcp-dev
  47. golang-github-xtaci-smux-dev
  48. golang-golang-x-crypto-dev
  49. golang-golang-x-net-dev
  50. golang-goptlib-dev
  51. golang-golang-x-sys-dev
  52. golang-golang-x-text-dev
  53. golang-golang-x-xerrors-dev
  54. # use Go installed as part of the official, Debian-based Docker images
  55. .golang-docker-debian-template: &golang-docker-debian-template
  56. before_script:
  57. - apt-get update
  58. - apt-get -qy install --no-install-recommends
  59. ca-certificates
  60. git
  61. .go-test: &go-test
  62. - gofmt -d .
  63. - test -z "$(go fmt ./...)"
  64. - go vet ./...
  65. - go test -v -race ./...
  66. - cd $CI_PROJECT_DIR/client/
  67. - go get
  68. - go build $REPRODUCIBLE_FLAGS
  69. .test-template: &test-template
  70. artifacts:
  71. name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_JOB_ID}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}"
  72. paths:
  73. - client/*.aar
  74. - client/*.jar
  75. - client/client
  76. expire_in: 1 week
  77. when: on_success
  78. after_script:
  79. - echo "Download debug artifacts from https://gitlab.com/${CI_PROJECT_PATH}/-/jobs"
  80. # this file changes every time but should not be cached
  81. - rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
  82. - rm -rf $GRADLE_USER_HOME/caches/*/plugin-resolution/
  83. # -- jobs ------------------------------------------------------------
  84. android:
  85. image: containers.torproject.org/tpo/anti-censorship/duplicatedcontainerimages:golang-1.23-$DEBIAN_STABLE
  86. variables:
  87. ANDROID_HOME: /usr/lib/android-sdk
  88. LANG: C.UTF-8
  89. cache:
  90. paths:
  91. - .gradle/wrapper
  92. - .gradle/caches
  93. <<: *test-template
  94. before_script:
  95. - *apt-template
  96. - apt-get install
  97. android-sdk-platform-23
  98. android-sdk-platform-tools
  99. build-essential
  100. curl
  101. default-jdk-headless
  102. git
  103. gnupg
  104. unzip
  105. wget
  106. ca-certificates
  107. - ndk=android-ndk-r21e-linux-x86_64.zip
  108. - wget --continue --no-verbose https://dl.google.com/android/repository/$ndk
  109. - echo "ad7ce5467e18d40050dc51b8e7affc3e635c85bd8c59be62de32352328ed467e $ndk" > $ndk.sha256
  110. - sha256sum -c $ndk.sha256
  111. - unzip -q $ndk
  112. - rm ${ndk}*
  113. - mv android-ndk-* $ANDROID_HOME/ndk-bundle/
  114. - chmod -R a+rX $ANDROID_HOME
  115. script:
  116. - *go-test
  117. - export GRADLE_USER_HOME=$CI_PROJECT_DIR/.gradle
  118. - go version
  119. - go env
  120. - go get golang.org/x/mobile/cmd/gomobile
  121. - go get golang.org/x/mobile/cmd/gobind
  122. - go install golang.org/x/mobile/cmd/gobind
  123. - go install golang.org/x/mobile/cmd/gomobile
  124. - gomobile init
  125. - cd $CI_PROJECT_DIR/client
  126. # gomobile builds a shared library not a CLI executable
  127. - sed -i 's,^package main$,package snowflakeclient,' *.go
  128. - go get golang.org/x/mobile/bind
  129. - gomobile bind -v -target=android $REPRODUCIBLE_FLAGS .
  130. go-1.21:
  131. image: containers.torproject.org/tpo/anti-censorship/duplicatedcontainerimages:golang-1.21-$DEBIAN_STABLE
  132. <<: *golang-docker-debian-template
  133. <<: *test-template
  134. script:
  135. - *go-test
  136. go-1.23:
  137. image: containers.torproject.org/tpo/anti-censorship/duplicatedcontainerimages:golang-1.23-$DEBIAN_STABLE
  138. <<: *golang-docker-debian-template
  139. <<: *test-template
  140. script:
  141. - *go-test
  142. debian-testing:
  143. image: debian:testing
  144. <<: *debian-native-template
  145. <<: *test-template
  146. script:
  147. - *go-test
  148. shadow-integration:
  149. image: containers.torproject.org/tpo/anti-censorship/duplicatedcontainerimages:golang-1.21-$DEBIAN_STABLE
  150. variables:
  151. SHADOW_VERSION: "193924aae0dab30ffda0abe29467f552949849fa"
  152. TGEN_VERSION: "v1.1.2"
  153. cache:
  154. key: sf-integration-$SHADOW_VERSION-$TGEN_VERSION
  155. paths:
  156. - /opt/
  157. artifacts:
  158. paths:
  159. - shadow.data.tar.gz
  160. when: on_failure
  161. tags:
  162. - amd64
  163. - tpa
  164. script:
  165. - apt-get update
  166. - apt-get install -y git tor
  167. - mkdir -p ~/.local/bin
  168. - mkdir -p ~/.local/src
  169. - export PATH=$PATH:$CI_PROJECT_DIR/opt/bin/
  170. # Install shadow and tgen
  171. - pushd ~/.local/src
  172. - |
  173. if [ ! -f opt/shadow/bin/shadow ]
  174. then
  175. echo "The required version of shadow was not cached, building from source"
  176. git clone --shallow-since=2021-08-01 https://github.com/shadow/shadow.git
  177. pushd shadow/
  178. git checkout $SHADOW_VERSION
  179. CONTAINER=debian:stable-slim ci/container_scripts/install_deps.sh
  180. CC=gcc CONTAINER=debian:stable-slim ci/container_scripts/install_extra_deps.sh
  181. export PATH="$HOME/.cargo/bin:${PATH}"
  182. ./setup build --jobs $(nproc) --prefix $CI_PROJECT_DIR/opt/
  183. ./setup install
  184. popd
  185. fi
  186. - |
  187. if [ ! -f opt/shadow/bin/tgen ]
  188. then
  189. echo "The required version of tgen was not cached, building from source"
  190. git clone --branch $TGEN_VERSION --depth 1 https://github.com/shadow/tgen.git
  191. pushd tgen/
  192. apt-get install -y cmake libglib2.0-dev libigraph-dev
  193. mkdir build && cd build
  194. cmake .. -DCMAKE_INSTALL_PREFIX=$CI_PROJECT_DIR/opt/
  195. make
  196. make install
  197. popd
  198. fi
  199. install $CI_PROJECT_DIR/opt/bin/tgen ~/.local/bin/tgen
  200. - popd
  201. # Apply snowflake patch(es)
  202. - |
  203. git clone --depth 1 https://github.com/cohosh/shadow-snowflake-minimal
  204. git am -3 shadow-snowflake-minimal/*.patch
  205. # Install snowflake binaries to .local folder
  206. - |
  207. for app in "proxy" "client" "server" "broker" "probetest"; do
  208. pushd $app
  209. go build
  210. install $app ~/.local/bin/snowflake-$app
  211. popd
  212. done
  213. # Install stun server
  214. - GOBIN=~/.local/bin go install github.com/gortc/stund@latest
  215. # Run a minimal snowflake shadow experiment
  216. - pushd shadow-snowflake-minimal/
  217. - shadow --log-level=debug --model-unblocked-syscall-latency=true snowflake-minimal.yaml > shadow.log
  218. - tar -czvf $CI_PROJECT_DIR/shadow.data.tar.gz shadow.data/
  219. # Check to make sure streams succeeded
  220. - |
  221. if [ $(grep -c "stream-success" shadow.data/hosts/snowflakeclient/tgen.*.stdout) = 10 ]
  222. then
  223. echo "All streams in shadow completed successfully"
  224. else
  225. echo "Shadow simulation failed"
  226. exit 1
  227. fi
  228. generate_tarball:
  229. stage: deploy
  230. image: golang:1.21-$DEBIAN_STABLE
  231. rules:
  232. - if: $CI_COMMIT_TAG
  233. script:
  234. - go mod vendor
  235. - tar czf ${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.gz --transform "s,^,${CI_PROJECT_NAME}-${CI_COMMIT_TAG}/," *
  236. after_script:
  237. - echo TAR_JOB_ID=$CI_JOB_ID >> generate_tarball.env
  238. artifacts:
  239. paths:
  240. - ${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.gz
  241. reports:
  242. dotenv: generate_tarball.env
  243. release-job:
  244. stage: deploy
  245. image: registry.gitlab.com/gitlab-org/release-cli:latest
  246. rules:
  247. - if: $CI_COMMIT_TAG
  248. needs:
  249. - job: generate_tarball
  250. artifacts: true
  251. script:
  252. - echo "running release_job"
  253. release:
  254. name: 'Release $CI_COMMIT_TAG'
  255. description: 'Created using the release-cli'
  256. tag_name: '$CI_COMMIT_TAG'
  257. ref: '$CI_COMMIT_TAG'
  258. assets:
  259. links:
  260. - name: '${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.gz'
  261. url: '${CI_PROJECT_URL}/-/jobs/${TAR_JOB_ID}/artifacts/file/${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.gz'
  262. # Build the container only if the commit is to main, or it is a tag.
  263. # If the commit is to main, then the docker image tag should be set to `nightly`.
  264. # If it is a tag, then the docker image tag should be set to the tag name.
  265. build-container:
  266. variables:
  267. TAG: $CI_COMMIT_TAG # Will not be set on a non-tag build, will be set later
  268. stage: container-build
  269. parallel:
  270. matrix:
  271. - ARCH: amd64
  272. - ARCH: arm64
  273. - ARCH: s390x
  274. tags:
  275. - $ARCH
  276. image:
  277. name: gcr.io/kaniko-project/executor:debug
  278. entrypoint: [""]
  279. script:
  280. - if [ $CI_COMMIT_REF_NAME == "main" ]; then export TAG='nightly'; fi
  281. - >-
  282. /kaniko/executor
  283. --context "${CI_PROJECT_DIR}"
  284. --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
  285. --destination "${CI_REGISTRY_IMAGE}:${TAG}_${ARCH}"
  286. rules:
  287. - if: $CI_COMMIT_REF_NAME == "main"
  288. - if: $CI_COMMIT_TAG
  289. merge-manifests:
  290. variables:
  291. TAG: $CI_COMMIT_TAG
  292. stage: container-build
  293. needs:
  294. - job: build-container
  295. artifacts: false
  296. image:
  297. name: containers.torproject.org/tpo/anti-censorship/duplicatedcontainerimages:mplatform-manifest-tool-alpine
  298. entrypoint: [""]
  299. script:
  300. - if [ $CI_COMMIT_REF_NAME == "main" ]; then export TAG='nightly'; fi
  301. - >-
  302. manifest-tool
  303. --username="${CI_REGISTRY_USER}"
  304. --password="${CI_REGISTRY_PASSWORD}"
  305. push from-args
  306. --platforms linux/amd64,linux/arm64,linux/s390x
  307. --template "${CI_REGISTRY_IMAGE}:${TAG}_ARCH"
  308. --target "${CI_REGISTRY_IMAGE}:${TAG}"
  309. rules:
  310. - if: $CI_COMMIT_REF_NAME == "main"
  311. when: always
  312. - if: $CI_COMMIT_TAG
  313. when: always
  314. # If this is a tag, then we want to additionally tag the image as `latest`
  315. tag-container-release:
  316. stage: container-build
  317. needs:
  318. - job: merge-manifests
  319. artifacts: false
  320. image:
  321. name: gcr.io/go-containerregistry/crane:debug
  322. entrypoint: [""]
  323. allow_failure: false
  324. variables:
  325. CI_REGISTRY: $CI_REGISTRY
  326. IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  327. RELEASE_TAG: $CI_REGISTRY_IMAGE:latest
  328. script:
  329. - echo "Tagging docker image with stable tag with crane"
  330. - echo -n "$CI_JOB_TOKEN" | crane auth login $CI_REGISTRY -u gitlab-ci-token --password-stdin
  331. - crane cp $IMAGE_TAG $RELEASE_TAG
  332. rules:
  333. - if: $CI_COMMIT_TAG
  334. when: always
  335. clean-image-tags:
  336. stage: container-build
  337. needs:
  338. - job: merge-manifests
  339. artifacts: false
  340. image: containers.torproject.org/tpo/tpa/base-images/debian:bookworm
  341. before_script:
  342. - *apt-template
  343. - apt-get install -y jq curl
  344. script:
  345. - "REGISTRY_ID=$(curl --silent --request GET --header \"JOB-TOKEN: ${CI_JOB_TOKEN}\" \"https://gitlab.torproject.org/api/v4/projects/${CI_PROJECT_ID}/registry/repositories\" | jq '.[].id')"
  346. - "curl --request DELETE --data \"name_regex_delete=(latest|${CI_COMMIT_TAG})_.*\" --header \"JOB-TOKEN: ${CI_JOB_TOKEN}\" \"https://gitlab.torproject.org/api/v4/projects/${CI_PROJECT_ID}/registry/repositories/${REGISTRY_ID}/tags\""
  347. rules:
  348. - if: $CI_COMMIT_REF_NAME == "main"
  349. when: always
  350. - if: $CI_COMMIT_TAG
  351. when: always
  352. mirror-image-to-dockerhub:
  353. stage: container-mirror
  354. variables:
  355. DOCKERHUB_MIRROR_REPOURL: $DOCKERHUB_MIRROR_REPOURL
  356. DOCKERHUB_USERNAME: $DOCKERHUB_MIRROR_USERNAME
  357. DOCKERHUB_PASSWORD: $DOCKERHUB_MIRROR_PASSWORD
  358. image:
  359. name: gcr.io/go-containerregistry/crane:debug
  360. entrypoint: [""]
  361. rules:
  362. - if: $CI_COMMIT_REF_NAME == "main"
  363. when: always
  364. - if: $CI_COMMIT_TAG
  365. when: always
  366. script:
  367. - echo "$DOCKERHUB_PASSWORD" | crane auth login docker.io -u $DOCKERHUB_MIRROR_USERNAME --password-stdin
  368. - crane cp -a containers.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake $DOCKERHUB_MIRROR_REPOURL