build-syncthing.yaml 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  1. name: Build Syncthing
  2. on:
  3. pull_request:
  4. push:
  5. branches-ignore:
  6. - release
  7. - release-rc*
  8. workflow_call:
  9. workflow_dispatch:
  10. env:
  11. # The go version to use for builds. We set check-latest to true when
  12. # installing, so we get the latest patch version that matches the
  13. # expression.
  14. GO_VERSION: "~1.24.0"
  15. # Optimize compatibility on the slow archictures.
  16. GOMIPS: softfloat
  17. GOARM: "6"
  18. # Avoid hilarious amounts of obscuring log output when running tests.
  19. LOGGER_DISCARD: "1"
  20. # Our build metadata
  21. BUILD_USER: builder
  22. BUILD_HOST: github.syncthing.net
  23. TAGS: "netgo osusergo sqlite_omit_load_extension sqlite_dbstat"
  24. # A note on actions and third party code... The actions under actions/ (like
  25. # `uses: actions/checkout`) are maintained by GitHub, and we need to trust
  26. # GitHub to maintain their code and infrastructure or we're in deep shit in
  27. # general. The same doesn't necessarily apply to other actions authors, so
  28. # some care needs to be taken when adding steps, especially in the paths
  29. # that lead up to code being packaged and signed.
  30. jobs:
  31. #
  32. # Tests for all platforms. Runs a matrix build on Windows, Linux and Mac,
  33. # with the list of expected supported Go versions (current, previous).
  34. #
  35. build-test:
  36. name: Build and test
  37. strategy:
  38. fail-fast: false
  39. matrix:
  40. runner: ["windows-latest", "ubuntu-latest", "macos-latest"]
  41. # The oldest version in this list should match what we have in our go.mod.
  42. # Variables don't seem to be supported here, or we could have done something nice.
  43. go: ["~1.23.0", "~1.24.0"]
  44. runs-on: ${{ matrix.runner }}
  45. steps:
  46. - name: Set git to use LF
  47. if: matrix.runner == 'windows-latest'
  48. # Without this, the Windows checkout will happen with CRLF line
  49. # endings, which is fine for the source code but messes up tests
  50. # that depend on data on disk being as expected. Ideally, those
  51. # tests should be fixed, but not today.
  52. run: |
  53. git config --global core.autocrlf false
  54. git config --global core.eol lf
  55. - uses: actions/checkout@v4
  56. - uses: actions/setup-go@v5
  57. with:
  58. go-version: ${{ matrix.go }}
  59. cache: true
  60. check-latest: true
  61. - name: Build
  62. run: |
  63. go run build.go
  64. - name: Install go-test-json-to-loki
  65. run: |
  66. go install calmh.dev/go-test-json-to-loki@latest
  67. - name: Test
  68. run: |
  69. go version
  70. go run build.go test | go-test-json-to-loki
  71. env:
  72. GOFLAGS: "-json"
  73. LOKI_URL: ${{ secrets.LOKI_URL }}
  74. LOKI_USER: ${{ secrets.LOKI_USER }}
  75. LOKI_PASSWORD: ${{ secrets.LOKI_PASSWORD }}
  76. LOKI_LABELS: "go=${{ matrix.go }},runner=${{ matrix.runner }},repo=${{ github.repository }},ref=${{ github.ref }}"
  77. CGO_ENABLED: "1"
  78. #
  79. # The basic checks job is a virtual one that depends on the matrix tests,
  80. # the correctness checks, and various builds that we always do. This makes
  81. # it easy to have the PR process have a single test as a gatekeeper for
  82. # merging, instead of having to add all the matrix tests and update them
  83. # each time the version changes. (The top level test is not available for
  84. # choosing there, only the matrix "children".)
  85. #
  86. basics:
  87. name: Basic checks passed
  88. runs-on: ubuntu-latest
  89. needs:
  90. - build-test
  91. - package-linux
  92. - package-cross
  93. - package-source
  94. - package-debian
  95. - package-windows
  96. - govulncheck
  97. - golangci
  98. - meta
  99. steps:
  100. - uses: actions/checkout@v4
  101. #
  102. # Windows
  103. #
  104. package-windows:
  105. name: Package for Windows
  106. runs-on: ubuntu-latest
  107. steps:
  108. - uses: actions/checkout@v4
  109. with:
  110. fetch-depth: 0
  111. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  112. - uses: actions/setup-go@v5
  113. with:
  114. go-version: ${{ env.GO_VERSION }}
  115. cache: false
  116. check-latest: true
  117. - uses: mlugg/setup-zig@v2
  118. - uses: actions/cache@v4
  119. with:
  120. path: |
  121. ~/.cache/go-build
  122. ~/go/pkg/mod
  123. key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-package-windows-${{ hashFiles('**/go.sum') }}
  124. - name: Install dependencies
  125. run: |
  126. go install github.com/josephspurrier/goversioninfo/cmd/[email protected]
  127. - name: Create packages
  128. run: |
  129. for tgt in syncthing stdiscosrv strelaysrv ; do
  130. go run build.go -tags "${{env.TAGS}}" -goos windows -goarch amd64 -cc "zig cc -target x86_64-windows" zip $tgt
  131. go run build.go -tags "${{env.TAGS}}" -goos windows -goarch 386 -cc "zig cc -target x86-windows" zip $tgt
  132. go run build.go -tags "${{env.TAGS}}" -goos windows -goarch arm64 -cc "zig cc -target aarch64-windows" zip $tgt
  133. # go run build.go -tags "${{env.TAGS}}" -goos windows -goarch arm -cc "zig cc -target thumb-windows" zip $tgt # failes with linker errors
  134. done
  135. env:
  136. CGO_ENABLED: "1"
  137. - name: Archive artifacts
  138. uses: actions/upload-artifact@v4
  139. with:
  140. name: unsigned-packages-windows
  141. path: "*.zip"
  142. #
  143. # Codesign binaries for Windows. This job runs only when called in the
  144. # Syncthing repo for release branches and tags, as it requires our
  145. # specific code signing keys etc.
  146. #
  147. codesign-windows:
  148. name: Codesign for Windows
  149. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
  150. environment: release
  151. runs-on: windows-latest
  152. needs:
  153. - package-windows
  154. steps:
  155. - name: Download artifacts
  156. uses: actions/download-artifact@v4
  157. with:
  158. name: unsigned-packages-windows
  159. path: packages
  160. - name: Extract packages
  161. working-directory: packages
  162. run: |
  163. $files = Get-ChildItem "." -Filter *.zip
  164. foreach ($file in $files) {
  165. 7z x $file.Name
  166. }
  167. - name: Sign files with Trusted Signing
  168. uses: azure/[email protected]
  169. with:
  170. azure-tenant-id: ${{ secrets.AZURE_TRUSTED_SIGNING_TENANT_ID }}
  171. azure-client-id: ${{ secrets.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
  172. azure-client-secret: ${{ secrets.AZURE_TRUSTED_SIGNING_CLIENT_SECRET }}
  173. endpoint: ${{ secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }}
  174. trusted-signing-account-name: ${{ secrets.AZURE_TRUSTED_SIGNING_ACCOUNT }}
  175. certificate-profile-name: ${{ secrets.AZURE_TRUSTED_SIGNING_PROFILE }}
  176. files-folder: ${{ github.workspace }}\packages
  177. files-folder-filter: exe
  178. files-folder-recurse: true
  179. file-digest: SHA256
  180. timestamp-rfc3161: http://timestamp.acs.microsoft.com
  181. timestamp-digest: SHA256
  182. - name: Repackage packages
  183. working-directory: packages
  184. run: |
  185. $files = Get-ChildItem "." -Filter *.zip
  186. foreach ($file in $files) {
  187. Remove-Item $file.Name
  188. 7z a -tzip $file.Name $file.BaseName
  189. }
  190. - name: Archive artifacts
  191. uses: actions/upload-artifact@v4
  192. with:
  193. name: packages-windows
  194. path: "packages/*.zip"
  195. #
  196. # Linux
  197. #
  198. package-linux:
  199. name: Package for Linux
  200. runs-on: ubuntu-latest
  201. steps:
  202. - uses: actions/checkout@v4
  203. with:
  204. fetch-depth: 0
  205. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  206. - uses: actions/setup-go@v5
  207. with:
  208. go-version: ${{ env.GO_VERSION }}
  209. cache: false
  210. check-latest: true
  211. - name: Get actual Go version
  212. run: |
  213. go version
  214. echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
  215. - uses: mlugg/setup-zig@v2
  216. - uses: actions/cache@v4
  217. with:
  218. path: |
  219. ~/.cache/go-build
  220. ~/go/pkg/mod
  221. key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-package-${{ hashFiles('**/go.sum') }}
  222. - name: Create packages
  223. run: |
  224. sudo apt-get install -y gcc-mips64-linux-gnuabi64 gcc-mips64el-linux-gnuabi64
  225. for tgt in syncthing stdiscosrv strelaysrv ; do
  226. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch amd64 -cc "zig cc -target x86_64-linux-musl" tar "$tgt"
  227. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch 386 -cc "zig cc -target x86-linux-musl" tar "$tgt"
  228. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch arm -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" tar "$tgt"
  229. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch arm64 -cc "zig cc -target aarch64-linux-musl" tar "$tgt"
  230. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mips -cc "zig cc -target mips-linux-musleabi" tar "$tgt"
  231. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mipsle -cc "zig cc -target mipsel-linux-musleabi" tar "$tgt"
  232. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mips64 -cc mips64-linux-gnuabi64-gcc tar "$tgt"
  233. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mips64le -cc mips64el-linux-gnuabi64-gcc tar "$tgt"
  234. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch riscv64 -cc "zig cc -target riscv64-linux-musl" tar "$tgt"
  235. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch s390x -cc "zig cc -target s390x-linux-musl" tar "$tgt"
  236. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch loong64 -cc "zig cc -target loongarch64-linux-musl" tar "$tgt"
  237. # go run build.go -tags "${{env.TAGS}}" -goos linux -goarch ppc64 -cc "zig cc -target powerpc64-linux-musl" tar "$tgt" # fails with linkmode not supported
  238. go run build.go -tags "${{env.TAGS}}" -goos linux -goarch ppc64le -cc "zig cc -target powerpc64le-linux-musl" tar "$tgt"
  239. done
  240. env:
  241. CGO_ENABLED: "1"
  242. EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
  243. - name: Archive artifacts
  244. uses: actions/upload-artifact@v4
  245. with:
  246. name: packages-linux
  247. path: |
  248. *.tar.gz
  249. compat.json
  250. #
  251. # macOS. The entire build runs in the release environment because code
  252. # signing is part of the build process, so it is limited to release
  253. # branches on the Syncthing repo.
  254. #
  255. package-macos:
  256. name: Package for macOS
  257. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
  258. environment: release
  259. env:
  260. CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }}
  261. runs-on: macos-latest
  262. steps:
  263. - uses: actions/checkout@v4
  264. with:
  265. fetch-depth: 0
  266. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  267. - uses: actions/setup-go@v5
  268. with:
  269. go-version: ${{ env.GO_VERSION }}
  270. cache: false
  271. check-latest: true
  272. - name: Get actual Go version
  273. run: |
  274. go version
  275. echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
  276. - uses: actions/cache@v4
  277. with:
  278. path: |
  279. ~/.cache/go-build
  280. ~/go/pkg/mod
  281. key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-package-${{ hashFiles('**/go.sum') }}
  282. - name: Import signing certificate
  283. if: env.CODESIGN_IDENTITY != ''
  284. run: |
  285. # Set up a run-specific keychain, making it available for the
  286. # `codesign` tool.
  287. umask 066
  288. KEYCHAIN_PATH=$RUNNER_TEMP/codesign.keychain
  289. KEYCHAIN_PASSWORD=$(uuidgen)
  290. security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
  291. security default-keychain -s "$KEYCHAIN_PATH"
  292. security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
  293. security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
  294. # Import the certificate
  295. CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
  296. echo "$DEVELOPER_ID_CERTIFICATE_BASE64" | base64 -d -o "$CERTIFICATE_PATH"
  297. security import "$CERTIFICATE_PATH" -k "$KEYCHAIN_PATH" -P "$DEVELOPER_ID_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
  298. security set-key-partition-list -S apple-tool:,apple: -s -k actions "$KEYCHAIN_PATH"
  299. # Set the codesign identity for following steps
  300. echo "CODESIGN_IDENTITY=$CODESIGN_IDENTITY" >> $GITHUB_ENV
  301. env:
  302. DEVELOPER_ID_CERTIFICATE_BASE64: ${{ secrets.DEVELOPER_ID_CERTIFICATE_BASE64 }}
  303. DEVELOPER_ID_CERTIFICATE_PASSWORD: ${{ secrets.DEVELOPER_ID_CERTIFICATE_PASSWORD }}
  304. CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }}
  305. - name: Create package (amd64)
  306. run: |
  307. for tgt in syncthing stdiscosrv strelaysrv ; do
  308. go run build.go -tags "${{env.TAGS}}" -goarch amd64 zip "$tgt"
  309. done
  310. env:
  311. CGO_ENABLED: "1"
  312. - name: Create package (arm64 cross)
  313. run: |
  314. cat <<EOT > xgo.sh
  315. #!/bin/bash
  316. CGO_ENABLED=1 \
  317. CGO_CFLAGS="-target arm64-apple-macos10.15" \
  318. CGO_LDFLAGS="-target arm64-apple-macos10.15" \
  319. go "\$@"
  320. EOT
  321. chmod 755 xgo.sh
  322. for tgt in syncthing stdiscosrv strelaysrv ; do
  323. go run build.go -tags "${{env.TAGS}}" -gocmd ./xgo.sh -goarch arm64 zip "$tgt"
  324. done
  325. env:
  326. CGO_ENABLED: "1"
  327. - name: Create package (universal)
  328. run: |
  329. rm -rf _tmp
  330. mkdir _tmp
  331. pushd _tmp
  332. unzip ../syncthing-macos-amd64-*.zip
  333. unzip ../syncthing-macos-arm64-*.zip
  334. lipo -create syncthing-macos-amd64-*/syncthing syncthing-macos-arm64-*/syncthing -o syncthing
  335. amd64=(syncthing-macos-amd64-*)
  336. universal="${amd64/amd64/universal}"
  337. mv "$amd64" "$universal"
  338. mv syncthing "$universal"
  339. zip -r "../$universal.zip" "$universal"
  340. - name: Archive artifacts
  341. uses: actions/upload-artifact@v4
  342. with:
  343. name: packages-macos
  344. path: "*.zip"
  345. notarize-macos:
  346. name: Notarize for macOS
  347. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
  348. environment: release
  349. needs:
  350. - package-macos
  351. runs-on: macos-latest
  352. steps:
  353. - name: Download artifacts
  354. uses: actions/download-artifact@v4
  355. with:
  356. name: packages-macos
  357. - name: Notarize binaries
  358. run: |
  359. APPSTORECONNECT_API_KEY_PATH="$RUNNER_TEMP/apikey.p8"
  360. echo "$APPSTORECONNECT_API_KEY" | base64 -d -o "$APPSTORECONNECT_API_KEY_PATH"
  361. for file in *-macos-*.zip ; do
  362. xcrun notarytool submit \
  363. -k "$APPSTORECONNECT_API_KEY_PATH" \
  364. -d "$APPSTORECONNECT_API_KEY_ID" \
  365. -i "$APPSTORECONNECT_API_KEY_ISSUER" \
  366. $file
  367. done
  368. env:
  369. APPSTORECONNECT_API_KEY: ${{ secrets.APPSTORECONNECT_API_KEY }}
  370. APPSTORECONNECT_API_KEY_ID: ${{ secrets.APPSTORECONNECT_API_KEY_ID }}
  371. APPSTORECONNECT_API_KEY_ISSUER: ${{ secrets.APPSTORECONNECT_API_KEY_ISSUER }}
  372. #
  373. # Cross compile other unixes
  374. #
  375. package-cross:
  376. name: Package cross compiled
  377. runs-on: ubuntu-latest
  378. steps:
  379. - uses: actions/checkout@v4
  380. with:
  381. fetch-depth: 0
  382. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  383. - uses: actions/setup-go@v5
  384. with:
  385. go-version: ${{ env.GO_VERSION }}
  386. cache: false
  387. check-latest: true
  388. - name: Get actual Go version
  389. run: |
  390. go version
  391. echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
  392. - uses: actions/cache@v4
  393. with:
  394. path: |
  395. ~/.cache/go-build
  396. ~/go/pkg/mod
  397. key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-cross-${{ hashFiles('**/go.sum') }}
  398. - name: Create packages
  399. run: |
  400. platforms=$(go tool dist list \
  401. | grep -v aix/ppc64 \
  402. | grep -v android/ \
  403. | grep -v darwin/ \
  404. | grep -v ios/ \
  405. | grep -v js/ \
  406. | grep -v linux/ \
  407. | grep -v nacl/ \
  408. | grep -v plan9/ \
  409. | grep -v windows/ \
  410. | grep -v /wasm \
  411. )
  412. # Build for each platform with errors silenced, because we expect
  413. # some oddball platforms to fail. This avoids a bunch of errors in
  414. # the GitHub Actions output, instead summarizing each build
  415. # failure as a warning.
  416. for plat in $platforms; do
  417. goos="${plat%/*}"
  418. goarch="${plat#*/}"
  419. echo "::group ::$plat"
  420. for tgt in syncthing stdiscosrv strelaysrv ; do
  421. if ! go run build.go -goos "$goos" -goarch "$goarch" tar "$tgt" ; then
  422. echo "::warning ::Failed to build $tgt for $plat"
  423. fi
  424. done
  425. echo "::endgroup::"
  426. done
  427. env:
  428. CGO_ENABLED: "0"
  429. - name: Archive artifacts
  430. uses: actions/upload-artifact@v4
  431. with:
  432. name: packages-other
  433. path: "*.tar.gz"
  434. #
  435. # Source
  436. #
  437. package-source:
  438. name: Package source code
  439. runs-on: ubuntu-latest
  440. steps:
  441. - uses: actions/checkout@v4
  442. with:
  443. fetch-depth: 0
  444. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  445. - uses: actions/setup-go@v5
  446. with:
  447. go-version: ${{ env.GO_VERSION }}
  448. cache: false
  449. check-latest: true
  450. - name: Package source
  451. run: |
  452. version=$(go run build.go version)
  453. echo "$version" > RELEASE
  454. go mod vendor
  455. go run build.go assets
  456. cd ..
  457. tar c -z -f "syncthing-source-$version.tar.gz" \
  458. --exclude .git \
  459. syncthing
  460. mv "syncthing-source-$version.tar.gz" syncthing
  461. - name: Archive artifacts
  462. uses: actions/upload-artifact@v4
  463. with:
  464. name: packages-source
  465. path: syncthing-source-*.tar.gz
  466. #
  467. # Sign binaries for auto upgrade, generate ASC signature files
  468. #
  469. sign-for-upgrade:
  470. name: Sign for upgrade
  471. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
  472. environment: release
  473. needs:
  474. - codesign-windows
  475. - package-linux
  476. - package-macos
  477. - package-cross
  478. - package-source
  479. runs-on: ubuntu-latest
  480. steps:
  481. - uses: actions/checkout@v4
  482. with:
  483. fetch-depth: 0
  484. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  485. - uses: actions/checkout@v4
  486. with:
  487. repository: syncthing/release-tools
  488. path: tools
  489. fetch-depth: 0
  490. - name: Download artifacts
  491. uses: actions/download-artifact@v4
  492. - uses: actions/setup-go@v5
  493. with:
  494. go-version: ${{ env.GO_VERSION }}
  495. cache: false
  496. check-latest: true
  497. - name: Install signing tool
  498. run: |
  499. go install ./cmd/dev/stsigtool
  500. - name: Sign archives
  501. run: |
  502. export PRIVATE_KEY="$RUNNER_TEMP/privkey.pem"
  503. export PATH="$PATH:$(go env GOPATH)/bin"
  504. echo "$STSIGTOOL_PRIVATE_KEY" | base64 -d > "$PRIVATE_KEY"
  505. mkdir packages
  506. mv packages-*/* packages
  507. pushd packages
  508. "$GITHUB_WORKSPACE/tools/sign-only"
  509. rm -f "$PRIVATE_KEY"
  510. env:
  511. STSIGTOOL_PRIVATE_KEY: ${{ secrets.STSIGTOOL_PRIVATE_KEY }}
  512. - name: Create shasum files
  513. run: |
  514. pushd packages
  515. files=(*.tar.gz *.zip)
  516. sha1sum "${files[@]}" > sha1sum.txt
  517. sha256sum "${files[@]}" > sha256sum.txt
  518. popd
  519. version=$(go run build.go version)
  520. echo "VERSION=$version" >> $GITHUB_ENV
  521. - name: Sign shasum files
  522. uses: docker://ghcr.io/kastelo/ezapt:latest
  523. with:
  524. args:
  525. sign
  526. packages/sha1sum.txt packages/sha256sum.txt
  527. env:
  528. EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
  529. - name: Sign source
  530. uses: docker://ghcr.io/kastelo/ezapt:latest
  531. with:
  532. args:
  533. sign --detach --ascii
  534. packages/syncthing-source-${{ env.VERSION }}.tar.gz
  535. env:
  536. EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
  537. - name: Archive artifacts
  538. uses: actions/upload-artifact@v4
  539. with:
  540. name: packages-signed
  541. path: |
  542. packages/*.tar.gz
  543. packages/*.zip
  544. packages/*.asc
  545. packages/*.json
  546. #
  547. # Debian
  548. #
  549. package-debian:
  550. name: Package for Debian
  551. runs-on: ubuntu-latest
  552. steps:
  553. - uses: actions/checkout@v4
  554. with:
  555. fetch-depth: 0
  556. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  557. - uses: actions/setup-go@v5
  558. with:
  559. go-version: ${{ env.GO_VERSION }}
  560. cache: false
  561. check-latest: true
  562. - name: Get actual Go version
  563. run: |
  564. go version
  565. echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
  566. - uses: ruby/setup-ruby@v1
  567. with:
  568. ruby-version: '3.0'
  569. - name: Install fpm
  570. run: |
  571. gem install fpm
  572. - uses: mlugg/setup-zig@v2
  573. - uses: actions/cache@v4
  574. with:
  575. path: |
  576. ~/.cache/go-build
  577. ~/go/pkg/mod
  578. key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-debian-${{ hashFiles('**/go.sum') }}
  579. - name: Package for Debian (CGO)
  580. run: |
  581. for tgt in syncthing stdiscosrv strelaysrv ; do
  582. go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS}}" -goos linux -goarch amd64 -cc "zig cc -target x86_64-linux-musl" deb "$tgt"
  583. go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS}}" -goos linux -goarch arm -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" deb "$tgt"
  584. go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS}}" -goos linux -goarch arm64 -cc "zig cc -target aarch64-linux-musl" deb "$tgt"
  585. done
  586. env:
  587. BUILD_USER: debian
  588. CGO_ENABLED: "1"
  589. EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
  590. - name: Archive artifacts
  591. uses: actions/upload-artifact@v4
  592. with:
  593. name: debian-packages
  594. path: "*.deb"
  595. #
  596. # Nightlies
  597. #
  598. publish-nightly:
  599. name: Publish nightly build
  600. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && startsWith(github.ref, 'refs/heads/release-nightly')
  601. environment: release
  602. needs:
  603. - sign-for-upgrade
  604. runs-on: ubuntu-latest
  605. steps:
  606. - uses: actions/checkout@v4
  607. with:
  608. repository: syncthing/release-tools
  609. path: tools
  610. fetch-depth: 0
  611. - name: Download artifacts
  612. uses: actions/download-artifact@v4
  613. with:
  614. name: packages-signed
  615. path: packages
  616. - uses: actions/setup-go@v5
  617. with:
  618. go-version: ${{ env.GO_VERSION }}
  619. cache: false
  620. check-latest: true
  621. - name: Create release json
  622. run: |
  623. cd packages
  624. "$GITHUB_WORKSPACE/tools/generate-release-json" "$BASE_URL" > nightly.json
  625. env:
  626. BASE_URL: ${{ secrets.NIGHTLY_BASE_URL }}
  627. - name: Push artifacts
  628. uses: docker://docker.io/rclone/rclone:latest
  629. env:
  630. RCLONE_CONFIG_OBJSTORE_TYPE: s3
  631. RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
  632. RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
  633. RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
  634. RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
  635. RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
  636. RCLONE_CONFIG_OBJSTORE_ACL: public-read
  637. with:
  638. args: sync -v packages objstore:nightly
  639. #
  640. # Push release artifacts to Spaces
  641. #
  642. publish-release-files:
  643. name: Publish release files
  644. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/tags/v'))
  645. environment: release
  646. permissions:
  647. contents: write
  648. needs:
  649. - sign-for-upgrade
  650. - package-debian
  651. runs-on: ubuntu-latest
  652. steps:
  653. - uses: actions/checkout@v4
  654. with:
  655. fetch-depth: 0
  656. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  657. - name: Download signed packages
  658. uses: actions/download-artifact@v4
  659. with:
  660. name: packages-signed
  661. path: packages
  662. - name: Download debian packages
  663. uses: actions/download-artifact@v4
  664. with:
  665. name: debian-packages
  666. path: packages
  667. - uses: actions/setup-go@v5
  668. with:
  669. go-version: ${{ env.GO_VERSION }}
  670. cache: false
  671. check-latest: true
  672. - name: Set version
  673. run: |
  674. version=$(go run build.go version)
  675. echo "VERSION=$version" >> $GITHUB_ENV
  676. - name: Push to object store (${{ env.VERSION }})
  677. uses: docker://docker.io/rclone/rclone:latest
  678. env:
  679. RCLONE_CONFIG_OBJSTORE_TYPE: s3
  680. RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
  681. RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
  682. RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
  683. RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
  684. RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
  685. RCLONE_CONFIG_OBJSTORE_ACL: public-read
  686. with:
  687. args: sync -v packages objstore:release/${{ env.VERSION }}
  688. - name: Push to object store (latest)
  689. uses: docker://docker.io/rclone/rclone:latest
  690. env:
  691. RCLONE_CONFIG_OBJSTORE_TYPE: s3
  692. RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
  693. RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
  694. RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
  695. RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
  696. RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
  697. RCLONE_CONFIG_OBJSTORE_ACL: public-read
  698. with:
  699. args: sync -v objstore:release/${{ env.VERSION }} objstore:release/latest
  700. - name: Create GitHub release and push binaries
  701. run: |
  702. maybePrerelease=""
  703. if [[ $VERSION == *-* ]]; then
  704. maybePrerelease="--prerelease"
  705. fi
  706. export GH_PROMPT_DISABLED=1
  707. if ! gh release view --json name "$VERSION" >/dev/null 2>&1 ; then
  708. gh release create \
  709. "$VERSION" \
  710. $maybePrerelease \
  711. --title "$VERSION" \
  712. --notes-from-tag
  713. fi
  714. gh release upload "$VERSION" \
  715. packages/*.asc packages/*.json \
  716. packages/syncthing-*.tar.gz \
  717. packages/syncthing-*.zip \
  718. packages/syncthing*.deb
  719. env:
  720. GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  721. #
  722. # Push Debian/APT archive
  723. #
  724. publish-apt:
  725. name: Publish APT
  726. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
  727. environment: release
  728. needs:
  729. - package-debian
  730. runs-on: ubuntu-latest
  731. steps:
  732. - uses: actions/checkout@v4
  733. with:
  734. fetch-depth: 0
  735. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  736. - name: Download packages
  737. uses: actions/download-artifact@v4
  738. with:
  739. name: debian-packages
  740. path: packages
  741. - name: Set version
  742. run: |
  743. version=$(go run build.go version)
  744. echo "Version: $version"
  745. echo "VERSION=$version" >> $GITHUB_ENV
  746. # Decide whether packages should go to stable, candidate or nightly
  747. - name: Prepare packages
  748. run: |
  749. kind=stable
  750. if [[ $VERSION == v2* ]] ; then
  751. kind=v2
  752. elif [[ $VERSION == *-rc.[0-9] ]] ; then
  753. kind=candidate
  754. elif [[ $VERSION == *-* ]] ; then
  755. kind=nightly
  756. fi
  757. echo "Kind: $kind"
  758. mkdir -p packages/syncthing/$kind
  759. mv packages/*.deb packages/syncthing/$kind
  760. - name: Pull archive
  761. uses: docker://docker.io/rclone/rclone:latest
  762. env:
  763. RCLONE_CONFIG_OBJSTORE_TYPE: s3
  764. RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
  765. RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
  766. RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
  767. RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
  768. RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
  769. RCLONE_CONFIG_OBJSTORE_ACL: public-read
  770. with:
  771. args: sync objstore:apt/dists dists
  772. - name: Update archive
  773. uses: docker://ghcr.io/kastelo/ezapt:latest
  774. with:
  775. args:
  776. publish
  777. --add packages
  778. --dists dists
  779. env:
  780. EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
  781. - name: Push archive
  782. uses: docker://docker.io/rclone/rclone:latest
  783. env:
  784. RCLONE_CONFIG_OBJSTORE_TYPE: s3
  785. RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
  786. RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
  787. RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
  788. RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
  789. RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
  790. RCLONE_CONFIG_OBJSTORE_ACL: public-read
  791. with:
  792. args: sync -v dists objstore:apt/dists
  793. #
  794. # Build and push (except for PRs) to GHCR.
  795. #
  796. docker-ghcr:
  797. name: Build and push Docker images (GHCR)
  798. runs-on: ubuntu-latest
  799. permissions:
  800. contents: read
  801. packages: write
  802. strategy:
  803. matrix:
  804. pkg:
  805. - syncthing
  806. - strelaysrv
  807. - stdiscosrv
  808. include:
  809. - pkg: syncthing
  810. dockerfile: Dockerfile
  811. image: syncthing
  812. - pkg: strelaysrv
  813. dockerfile: Dockerfile.strelaysrv
  814. image: relaysrv
  815. - pkg: stdiscosrv
  816. dockerfile: Dockerfile.stdiscosrv
  817. image: discosrv
  818. steps:
  819. - uses: actions/checkout@v4
  820. with:
  821. fetch-depth: 0
  822. ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
  823. - uses: actions/setup-go@v5
  824. with:
  825. go-version: ${{ env.GO_VERSION }}
  826. cache: false
  827. check-latest: true
  828. - name: Get actual Go version
  829. run: |
  830. go version
  831. echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
  832. - uses: mlugg/setup-zig@v2
  833. - uses: actions/cache@v4
  834. with:
  835. path: |
  836. ~/.cache/go-build
  837. ~/go/pkg/mod
  838. key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-docker-${{ matrix.pkg }}-${{ hashFiles('**/go.sum') }}
  839. - name: Build binaries (CGO)
  840. run: |
  841. # amd64
  842. go run build.go -goos linux -goarch amd64 -tags "${{env.TAGS}}" -cc "zig cc -target x86_64-linux-musl" -no-upgrade build ${{ matrix.pkg }}
  843. mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-amd64
  844. # arm64
  845. go run build.go -goos linux -goarch arm64 -tags "${{env.TAGS}}" -cc "zig cc -target aarch64-linux-musl" -no-upgrade build ${{ matrix.pkg }}
  846. mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-arm64
  847. # arm
  848. go run build.go -goos linux -goarch arm -tags "${{env.TAGS}}" -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" -no-upgrade build ${{ matrix.pkg }}
  849. mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-arm
  850. env:
  851. CGO_ENABLED: "1"
  852. BUILD_USER: docker
  853. EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
  854. - name: Login to GHCR
  855. uses: docker/login-action@v3
  856. with:
  857. registry: ghcr.io
  858. username: ${{ github.actor }}
  859. password: ${{ secrets.GITHUB_TOKEN }}
  860. - name: Set up Docker Buildx
  861. uses: docker/setup-buildx-action@v3
  862. - name: Set version tags
  863. run: |
  864. version=$(go run build.go version)
  865. version=${version#v}
  866. repo=ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}
  867. ref="${{github.ref_name}}"
  868. ref=${ref//\//-} # slashes to dashes
  869. # List of tags for ghcr.io
  870. if [[ $version == @([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]) ]] ; then
  871. major=${version%.*.*}
  872. minor=${version%.*}
  873. tags=$repo:$version,$repo:$major,$repo:$minor,$repo:latest
  874. elif [[ $version == *-rc.@([0-9]|[0-9][0-9]) ]] ; then
  875. tags=$repo:$version,$repo:rc
  876. elif [[ $ref == "main" ]] ; then
  877. tags=$repo:edge
  878. else
  879. tags=$repo:$ref
  880. fi
  881. echo Pushing to $tags
  882. echo "DOCKER_TAGS=$tags" >> $GITHUB_ENV
  883. echo "VERSION=$version" >> $GITHUB_ENV
  884. - name: Build and push Docker image
  885. uses: docker/build-push-action@v5
  886. with:
  887. context: .
  888. file: ${{ matrix.dockerfile }}
  889. platforms: linux/amd64,linux/arm64,linux/arm/7
  890. tags: ${{ env.DOCKER_TAGS }}
  891. push: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
  892. labels: |
  893. org.opencontainers.image.version=${{ env.VERSION }}
  894. org.opencontainers.image.revision=${{ github.sha }}
  895. #
  896. # Sync images to Docker hub. This takes the images already pushed to GHCR
  897. # and copies them to Docker hub. Runs for releases only.
  898. #
  899. docker-hub:
  900. name: Sync images to Docker hub
  901. if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release-nightly' || github.ref == 'refs/heads/infrastructure' || startsWith(github.ref, 'refs/tags/v'))
  902. runs-on: ubuntu-latest
  903. needs:
  904. - docker-ghcr
  905. environment: docker
  906. env:
  907. DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
  908. DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
  909. steps:
  910. - uses: actions/checkout@v4
  911. - name: Sync images
  912. uses: docker://docker.io/regclient/regsync:latest
  913. with:
  914. args:
  915. -c ./.github/regsync.yml
  916. once
  917. #
  918. # Check for known vulnerabilities in Go dependencies
  919. #
  920. govulncheck:
  921. runs-on: ubuntu-latest
  922. name: Run govulncheck
  923. steps:
  924. - uses: actions/checkout@v4
  925. - uses: actions/setup-go@v5
  926. with:
  927. go-version: ${{ env.GO_VERSION }}
  928. cache: false
  929. check-latest: true
  930. - name: run govulncheck
  931. run: |
  932. go run build.go assets
  933. go install golang.org/x/vuln/cmd/govulncheck@latest
  934. govulncheck ./...
  935. #
  936. # golangci-lint runs a suite of static analysis checks on the code
  937. #
  938. golangci:
  939. runs-on: ubuntu-latest
  940. name: Run golangci-lint
  941. steps:
  942. - uses: actions/checkout@v4
  943. - uses: actions/setup-go@v5
  944. with:
  945. go-version: 'stable'
  946. - name: ensure asset generation
  947. run: go run build.go assets
  948. - name: golangci-lint
  949. uses: golangci/golangci-lint-action@v8
  950. with:
  951. only-new-issues: true
  952. #
  953. # Meta checks for formatting, copyright, etc
  954. #
  955. meta:
  956. name: Run meta checks
  957. runs-on: ubuntu-latest
  958. steps:
  959. - uses: actions/checkout@v4
  960. - uses: actions/setup-go@v5
  961. with:
  962. go-version: 'stable'
  963. - run: |
  964. go run build.go assets
  965. go test -v ./meta