| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124 |
- name: Build Syncthing
- on:
- pull_request:
- push:
- branches-ignore:
- - release
- - release-rc*
- workflow_call:
- workflow_dispatch:
- env:
- # The go version to use for builds. We set check-latest to true when
- # installing, so we get the latest patch version that matches the
- # expression.
- GO_VERSION: "~1.24.0"
- # Optimize compatibility on the slow archictures.
- GOMIPS: softfloat
- GOARM: "6"
- # Avoid hilarious amounts of obscuring log output when running tests.
- LOGGER_DISCARD: "1"
- # Our build metadata
- BUILD_USER: builder
- BUILD_HOST: github.syncthing.net
- TAGS: "netgo osusergo sqlite_omit_load_extension sqlite_dbstat"
- # A note on actions and third party code... The actions under actions/ (like
- # `uses: actions/checkout`) are maintained by GitHub, and we need to trust
- # GitHub to maintain their code and infrastructure or we're in deep shit in
- # general. The same doesn't necessarily apply to other actions authors, so
- # some care needs to be taken when adding steps, especially in the paths
- # that lead up to code being packaged and signed.
- jobs:
- #
- # Source
- #
- facts:
- name: Gather common facts
- runs-on: ubuntu-latest
- outputs:
- version: ${{ steps.get-version.outputs.version }}
- release-kind: ${{ steps.get-version.outputs.release-kind }}
- go-version: ${{ steps.get-go.outputs.go-version }}
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ env.GO_VERSION }}
- cache: false
- check-latest: true
- - name: Get Syncthing version
- id: get-version
- run: |
- version=$(go run build.go version)
- echo "version=$version" >> "$GITHUB_OUTPUT"
- echo "Version: $version"
- kind=stable
- if [[ $version == *-rc.[0-9] || $version == *-rc.[0-9][0-9] ]] ; then
- kind=candidate
- elif [[ $version == *-* ]] ; then
- kind=nightly
- fi
- echo "release-kind=$kind" >> "$GITHUB_OUTPUT"
- echo "Release kind: $kind"
- - name: Get Go version
- id: get-go
- run: |
- go version
- echo "go-version=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_OUTPUT
- #
- # Tests for all platforms. Runs a matrix build on Windows, Linux and Mac,
- # with the list of expected supported Go versions (current, previous).
- #
- build-test:
- name: Build and test
- strategy:
- fail-fast: false
- matrix:
- runner: ["windows-latest", "ubuntu-latest", "macos-latest"]
- # The oldest version in this list should match what we have in our go.mod.
- # Variables don't seem to be supported here, or we could have done something nice.
- go: ["~1.23.0", "~1.24.0"]
- runs-on: ${{ matrix.runner }}
- steps:
- - name: Set git to use LF
- if: matrix.runner == 'windows-latest'
- # Without this, the Windows checkout will happen with CRLF line
- # endings, which is fine for the source code but messes up tests
- # that depend on data on disk being as expected. Ideally, those
- # tests should be fixed, but not today.
- run: |
- git config --global core.autocrlf false
- git config --global core.eol lf
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ matrix.go }}
- cache: true
- check-latest: true
- - name: Build
- run: |
- go run build.go
- - name: Install go-test-json-to-loki
- run: |
- go install calmh.dev/go-test-json-to-loki@latest
- - name: Test
- run: |
- go version
- go run build.go test | go-test-json-to-loki
- env:
- GOFLAGS: "-json"
- LOKI_URL: ${{ secrets.LOKI_URL }}
- LOKI_USER: ${{ secrets.LOKI_USER }}
- LOKI_PASSWORD: ${{ secrets.LOKI_PASSWORD }}
- LOKI_LABELS: "go=${{ matrix.go }},runner=${{ matrix.runner }},repo=${{ github.repository }},ref=${{ github.ref }}"
- CGO_ENABLED: "1"
- #
- # The basic checks job is a virtual one that depends on the matrix tests,
- # the correctness checks, and various builds that we always do. This makes
- # it easy to have the PR process have a single test as a gatekeeper for
- # merging, instead of having to add all the matrix tests and update them
- # each time the version changes. (The top level test is not available for
- # choosing there, only the matrix "children".)
- #
- basics:
- name: Basic checks passed
- runs-on: ubuntu-latest
- needs:
- - build-test
- - package-linux
- - package-cross
- - package-source
- - package-debian
- - package-windows
- - govulncheck
- - golangci
- - meta
- steps:
- - uses: actions/checkout@v4
- #
- # Windows
- #
- package-windows:
- name: Package for Windows
- runs-on: ubuntu-latest
- needs:
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - uses: mlugg/setup-zig@v2
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cache/go-build
- ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-package-windows-${{ hashFiles('**/go.sum') }}
- - name: Install dependencies
- run: |
- go install github.com/josephspurrier/goversioninfo/cmd/[email protected]
- - name: Create packages
- run: |
- for tgt in syncthing stdiscosrv strelaysrv ; do
- go run build.go -tags "${{env.TAGS}}" -goos windows -goarch amd64 -cc "zig cc -target x86_64-windows" zip $tgt
- go run build.go -tags "${{env.TAGS}}" -goos windows -goarch 386 -cc "zig cc -target x86-windows" zip $tgt
- go run build.go -tags "${{env.TAGS}}" -goos windows -goarch arm64 -cc "zig cc -target aarch64-windows" zip $tgt
- # go run build.go -tags "${{env.TAGS}}" -goos windows -goarch arm -cc "zig cc -target thumb-windows" zip $tgt # failes with linker errors
- done
- env:
- CGO_ENABLED: "1"
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: unsigned-packages-windows
- path: "*.zip"
- #
- # Codesign binaries for Windows. This job runs only when called in the
- # Syncthing repo for release branches and tags, as it requires our
- # specific code signing keys etc.
- #
- codesign-windows:
- name: Codesign for Windows
- 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'))
- environment: release
- runs-on: windows-latest
- needs:
- - package-windows
- steps:
- - name: Download artifacts
- uses: actions/download-artifact@v4
- with:
- name: unsigned-packages-windows
- path: packages
- - name: Extract packages
- working-directory: packages
- run: |
- $files = Get-ChildItem "." -Filter *.zip
- foreach ($file in $files) {
- 7z x $file.Name
- }
- - name: Sign files with Trusted Signing
- uses: azure/[email protected]
- with:
- azure-tenant-id: ${{ secrets.AZURE_TRUSTED_SIGNING_TENANT_ID }}
- azure-client-id: ${{ secrets.AZURE_TRUSTED_SIGNING_CLIENT_ID }}
- azure-client-secret: ${{ secrets.AZURE_TRUSTED_SIGNING_CLIENT_SECRET }}
- endpoint: ${{ secrets.AZURE_TRUSTED_SIGNING_ENDPOINT }}
- trusted-signing-account-name: ${{ secrets.AZURE_TRUSTED_SIGNING_ACCOUNT }}
- certificate-profile-name: ${{ secrets.AZURE_TRUSTED_SIGNING_PROFILE }}
- files-folder: ${{ github.workspace }}\packages
- files-folder-filter: exe
- files-folder-recurse: true
- file-digest: SHA256
- timestamp-rfc3161: http://timestamp.acs.microsoft.com
- timestamp-digest: SHA256
- - name: Repackage packages
- working-directory: packages
- run: |
- $files = Get-ChildItem "." -Filter *.zip
- foreach ($file in $files) {
- Remove-Item $file.Name
- 7z a -tzip $file.Name $file.BaseName
- }
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: packages-windows
- path: "packages/*.zip"
- #
- # Linux
- #
- package-linux:
- name: Package for Linux
- runs-on: ubuntu-latest
- needs:
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - uses: mlugg/setup-zig@v2
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cache/go-build
- ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-package-${{ hashFiles('**/go.sum') }}
- - name: Create packages
- run: |
- sudo apt-get install -y gcc-mips64-linux-gnuabi64 gcc-mips64el-linux-gnuabi64
- for tgt in syncthing stdiscosrv strelaysrv ; do
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch amd64 -cc "zig cc -target x86_64-linux-musl" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch 386 -cc "zig cc -target x86-linux-musl" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch arm -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch arm64 -cc "zig cc -target aarch64-linux-musl" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mips -cc "zig cc -target mips-linux-musleabi" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mipsle -cc "zig cc -target mipsel-linux-musleabi" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mips64 -cc mips64-linux-gnuabi64-gcc tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch mips64le -cc mips64el-linux-gnuabi64-gcc tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch riscv64 -cc "zig cc -target riscv64-linux-musl" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch s390x -cc "zig cc -target s390x-linux-musl" tar "$tgt"
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch loong64 -cc "zig cc -target loongarch64-linux-musl" tar "$tgt"
- # 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
- go run build.go -tags "${{env.TAGS}}" -goos linux -goarch ppc64le -cc "zig cc -target powerpc64le-linux-musl" tar "$tgt"
- done
- env:
- CGO_ENABLED: "1"
- EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: packages-linux
- path: |
- *.tar.gz
- compat.json
- #
- # macOS. The entire build runs in the release environment because code
- # signing is part of the build process, so it is limited to release
- # branches on the Syncthing repo.
- #
- package-macos:
- name: Package for macOS
- 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'))
- environment: release
- runs-on: macos-latest
- needs:
- - facts
- env:
- CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }}
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cache/go-build
- ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-package-${{ hashFiles('**/go.sum') }}
- - name: Import signing certificate
- if: env.CODESIGN_IDENTITY != ''
- run: |
- # Set up a run-specific keychain, making it available for the
- # `codesign` tool.
- umask 066
- KEYCHAIN_PATH=$RUNNER_TEMP/codesign.keychain
- KEYCHAIN_PASSWORD=$(uuidgen)
- security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
- security default-keychain -s "$KEYCHAIN_PATH"
- security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
- security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
- # Import the certificate
- CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
- echo "$DEVELOPER_ID_CERTIFICATE_BASE64" | base64 -d -o "$CERTIFICATE_PATH"
- security import "$CERTIFICATE_PATH" -k "$KEYCHAIN_PATH" -P "$DEVELOPER_ID_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
- security set-key-partition-list -S apple-tool:,apple: -s -k actions "$KEYCHAIN_PATH"
- # Set the codesign identity for following steps
- echo "CODESIGN_IDENTITY=$CODESIGN_IDENTITY" >> $GITHUB_ENV
- env:
- DEVELOPER_ID_CERTIFICATE_BASE64: ${{ secrets.DEVELOPER_ID_CERTIFICATE_BASE64 }}
- DEVELOPER_ID_CERTIFICATE_PASSWORD: ${{ secrets.DEVELOPER_ID_CERTIFICATE_PASSWORD }}
- CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }}
- - name: Create package (amd64)
- run: |
- for tgt in syncthing stdiscosrv strelaysrv ; do
- go run build.go -tags "${{env.TAGS}}" -goarch amd64 zip "$tgt"
- done
- env:
- CGO_ENABLED: "1"
- - name: Create package (arm64 cross)
- run: |
- cat <<EOT > xgo.sh
- #!/bin/bash
- CGO_ENABLED=1 \
- CGO_CFLAGS="-target arm64-apple-macos10.15" \
- CGO_LDFLAGS="-target arm64-apple-macos10.15" \
- go "\$@"
- EOT
- chmod 755 xgo.sh
- for tgt in syncthing stdiscosrv strelaysrv ; do
- go run build.go -tags "${{env.TAGS}}" -gocmd ./xgo.sh -goarch arm64 zip "$tgt"
- done
- env:
- CGO_ENABLED: "1"
- - name: Create package (universal)
- run: |
- rm -rf _tmp
- mkdir _tmp
- pushd _tmp
- unzip ../syncthing-macos-amd64-*.zip
- unzip ../syncthing-macos-arm64-*.zip
- lipo -create syncthing-macos-amd64-*/syncthing syncthing-macos-arm64-*/syncthing -o syncthing
- amd64=(syncthing-macos-amd64-*)
- universal="${amd64/amd64/universal}"
- mv "$amd64" "$universal"
- mv syncthing "$universal"
- zip -r "../$universal.zip" "$universal"
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: packages-macos
- path: "*.zip"
- notarize-macos:
- name: Notarize for macOS
- 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'))
- environment: release
- needs:
- - package-macos
- runs-on: macos-latest
- steps:
- - name: Download artifacts
- uses: actions/download-artifact@v4
- with:
- name: packages-macos
- - name: Notarize binaries
- run: |
- APPSTORECONNECT_API_KEY_PATH="$RUNNER_TEMP/apikey.p8"
- echo "$APPSTORECONNECT_API_KEY" | base64 -d -o "$APPSTORECONNECT_API_KEY_PATH"
- for file in *-macos-*.zip ; do
- xcrun notarytool submit \
- -k "$APPSTORECONNECT_API_KEY_PATH" \
- -d "$APPSTORECONNECT_API_KEY_ID" \
- -i "$APPSTORECONNECT_API_KEY_ISSUER" \
- $file
- done
- env:
- APPSTORECONNECT_API_KEY: ${{ secrets.APPSTORECONNECT_API_KEY }}
- APPSTORECONNECT_API_KEY_ID: ${{ secrets.APPSTORECONNECT_API_KEY_ID }}
- APPSTORECONNECT_API_KEY_ISSUER: ${{ secrets.APPSTORECONNECT_API_KEY_ISSUER }}
- #
- # Cross compile other unixes
- #
- package-cross:
- name: Package cross compiled
- runs-on: ubuntu-latest
- needs:
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cache/go-build
- ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-cross-${{ hashFiles('**/go.sum') }}
- - name: Create packages
- run: |
- platforms=$(go tool dist list \
- | grep -v aix/ppc64 \
- | grep -v android/ \
- | grep -v darwin/ \
- | grep -v ios/ \
- | grep -v js/ \
- | grep -v linux/ \
- | grep -v nacl/ \
- | grep -v plan9/ \
- | grep -v windows/ \
- | grep -v /wasm \
- )
- # Build for each platform with errors silenced, because we expect
- # some oddball platforms to fail. This avoids a bunch of errors in
- # the GitHub Actions output, instead summarizing each build
- # failure as a warning.
- for plat in $platforms; do
- goos="${plat%/*}"
- goarch="${plat#*/}"
- echo "::group ::$plat"
- for tgt in syncthing stdiscosrv strelaysrv ; do
- if ! go run build.go -goos "$goos" -goarch "$goarch" tar "$tgt" ; then
- echo "::warning ::Failed to build $tgt for $plat"
- fi
- done
- echo "::endgroup::"
- done
- env:
- CGO_ENABLED: "0"
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: packages-other
- path: "*.tar.gz"
- #
- # Source
- #
- package-source:
- name: Package source code
- runs-on: ubuntu-latest
- needs:
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - name: Package source
- run: |
- echo "$VERSION" > RELEASE
- go mod vendor
- go run build.go assets
- cd ..
- tar c -z -f "syncthing-source-$VERSION.tar.gz" \
- --exclude .git \
- syncthing
- mv "syncthing-source-$VERSION.tar.gz" syncthing
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: packages-source
- path: syncthing-source-*.tar.gz
- #
- # Sign binaries for auto upgrade, generate ASC signature files
- #
- sign-for-upgrade:
- name: Sign for upgrade
- 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'))
- environment: release
- needs:
- - codesign-windows
- - package-linux
- - package-macos
- - package-cross
- - package-source
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/checkout@v4
- with:
- repository: syncthing/release-tools
- path: tools
- - name: Download artifacts
- uses: actions/download-artifact@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - name: Install signing tool
- run: |
- go install ./cmd/dev/stsigtool
- - name: Sign archives
- run: |
- export PRIVATE_KEY="$RUNNER_TEMP/privkey.pem"
- export PATH="$PATH:$(go env GOPATH)/bin"
- echo "$STSIGTOOL_PRIVATE_KEY" | base64 -d > "$PRIVATE_KEY"
- mkdir packages
- mv packages-*/* packages
- pushd packages
- "$GITHUB_WORKSPACE/tools/sign-only"
- rm -f "$PRIVATE_KEY"
- env:
- STSIGTOOL_PRIVATE_KEY: ${{ secrets.STSIGTOOL_PRIVATE_KEY }}
- - name: Create shasum files
- run: |
- pushd packages
- files=(*.tar.gz *.zip)
- sha1sum "${files[@]}" > sha1sum.txt
- sha256sum "${files[@]}" > sha256sum.txt
- popd
- - name: Sign shasum files
- uses: docker://ghcr.io/kastelo/ezapt:latest
- with:
- args:
- sign
- packages/sha1sum.txt packages/sha256sum.txt
- env:
- EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
- - name: Sign source
- uses: docker://ghcr.io/kastelo/ezapt:latest
- with:
- args:
- sign --detach --ascii
- packages/syncthing-source-${{ env.VERSION }}.tar.gz
- env:
- EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: packages-signed
- path: |
- packages/*.tar.gz
- packages/*.zip
- packages/*.asc
- packages/*.json
- #
- # Debian
- #
- package-debian:
- name: Package for Debian
- runs-on: ubuntu-latest
- needs:
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - uses: ruby/setup-ruby@v1
- with:
- ruby-version: '3.0'
- - name: Install fpm
- run: |
- gem install fpm
- - uses: mlugg/setup-zig@v2
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cache/go-build
- ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-debian-${{ hashFiles('**/go.sum') }}
- - name: Package for Debian (CGO)
- run: |
- for tgt in syncthing stdiscosrv strelaysrv ; do
- 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"
- 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"
- 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"
- done
- env:
- BUILD_USER: debian
- CGO_ENABLED: "1"
- EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
- - name: Archive artifacts
- uses: actions/upload-artifact@v4
- with:
- name: debian-packages
- path: "*.deb"
- #
- # Nightlies
- #
- publish-nightly:
- name: Publish nightly build
- if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && startsWith(github.ref, 'refs/heads/release-nightly')
- environment: release
- needs:
- - sign-for-upgrade
- - facts
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- repository: syncthing/release-tools
- path: tools
- - name: Download artifacts
- uses: actions/download-artifact@v4
- with:
- name: packages-signed
- path: packages
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - name: Create release json
- run: |
- cd packages
- "$GITHUB_WORKSPACE/tools/generate-release-json" "$BASE_URL" > nightly.json
- env:
- BASE_URL: ${{ secrets.NIGHTLY_BASE_URL }}
- - name: Push artifacts
- uses: docker://docker.io/rclone/rclone:latest
- env:
- RCLONE_CONFIG_OBJSTORE_TYPE: s3
- RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
- RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
- RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
- RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
- RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
- RCLONE_CONFIG_OBJSTORE_ACL: public-read
- with:
- args: sync -v --no-update-modtime packages objstore:nightly
- #
- # Push release artifacts to Spaces
- #
- publish-release-files:
- name: Publish release files
- 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'))
- environment: release
- permissions:
- contents: write
- needs:
- - sign-for-upgrade
- - package-debian
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Download signed packages
- uses: actions/download-artifact@v4
- with:
- name: packages-signed
- path: packages
- - name: Download debian packages
- uses: actions/download-artifact@v4
- with:
- name: debian-packages
- path: packages
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - name: Push to object store (${{ env.VERSION }})
- uses: docker://docker.io/rclone/rclone:latest
- env:
- RCLONE_CONFIG_OBJSTORE_TYPE: s3
- RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
- RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
- RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
- RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
- RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
- RCLONE_CONFIG_OBJSTORE_ACL: public-read
- with:
- args: sync -v --no-update-modtime packages objstore:release/${{ env.VERSION }}
- - name: Push to object store (latest)
- uses: docker://docker.io/rclone/rclone:latest
- env:
- RCLONE_CONFIG_OBJSTORE_TYPE: s3
- RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
- RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
- RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
- RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
- RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
- RCLONE_CONFIG_OBJSTORE_ACL: public-read
- with:
- args: sync -v --no-update-modtime objstore:release/${{ env.VERSION }} objstore:release/latest
- - name: Create GitHub releases and push binaries
- run: |
- maybePrerelease=""
- if [[ $VERSION == *-* ]]; then
- maybePrerelease="--prerelease"
- fi
- export GH_PROMPT_DISABLED=1
- if ! gh release view --json name "$VERSION" >/dev/null 2>&1 ; then
- gh release create "$VERSION" \
- $maybePrerelease \
- --title "$VERSION" \
- --notes-from-tag
- fi
- gh release upload --clobber "$VERSION" \
- packages/*.asc packages/*.json \
- packages/syncthing-*.tar.gz \
- packages/syncthing-*.zip \
- packages/syncthing_*.deb
- PKGS=$(pwd)/packages
- cd /tmp # gh will not release for repo x while inside repo y
- for repo in relaysrv discosrv ; do
- export GH_REPO="syncthing/$repo"
- if ! gh release view --json name "$VERSION" >/dev/null 2>&1 ; then
- gh release create "$VERSION" \
- $maybePrerelease \
- --title "$VERSION" \
- --notes "https://github.com/syncthing/syncthing/releases/tag/$VERSION"
- fi
- gh release upload --clobber "$VERSION" \
- $PKGS/*.asc \
- $PKGS/*${repo}*
- done
- env:
- GH_TOKEN: ${{ secrets.ACTIONS_GITHUB_TOKEN }}
- #
- # Push Debian/APT archive
- #
- publish-apt:
- name: Publish APT
- 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'))
- environment: release
- needs:
- - package-debian
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Download packages
- uses: actions/download-artifact@v4
- with:
- name: debian-packages
- path: packages
- # Decide whether packages should go to stable, candidate or nightly
- - name: Prepare packages
- run: |
- mkdir -p packages/syncthing/$RELEASE_KIND
- mv packages/*.deb packages/syncthing/$RELEASE_KIND
- - name: Pull archive
- uses: docker://docker.io/rclone/rclone:latest
- env:
- RCLONE_CONFIG_OBJSTORE_TYPE: s3
- RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
- RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
- RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
- RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
- RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
- RCLONE_CONFIG_OBJSTORE_ACL: public-read
- with:
- args: sync objstore:apt/dists dists
- - name: Update archive
- uses: docker://ghcr.io/kastelo/ezapt:latest
- with:
- args:
- publish
- --add packages
- --dists dists
- env:
- EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
- - name: Push archive
- uses: docker://docker.io/rclone/rclone:latest
- env:
- RCLONE_CONFIG_OBJSTORE_TYPE: s3
- RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
- RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
- RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
- RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
- RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
- RCLONE_CONFIG_OBJSTORE_ACL: public-read
- with:
- args: sync -v --no-update-modtime dists objstore:apt/dists
- #
- # Build and push (except for PRs) to GHCR.
- #
- docker-ghcr:
- name: Build and push Docker images (GHCR)
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- needs:
- - facts
- env:
- VERSION: ${{ needs.facts.outputs.version }}
- RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
- strategy:
- matrix:
- pkg:
- - syncthing
- - strelaysrv
- - stdiscosrv
- include:
- - pkg: syncthing
- dockerfile: Dockerfile
- image: syncthing
- - pkg: strelaysrv
- dockerfile: Dockerfile.strelaysrv
- image: relaysrv
- - pkg: stdiscosrv
- dockerfile: Dockerfile.stdiscosrv
- image: discosrv
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - uses: mlugg/setup-zig@v2
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cache/go-build
- ~/go/pkg/mod
- key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-docker-${{ matrix.pkg }}-${{ hashFiles('**/go.sum') }}
- - name: Build binaries (CGO)
- run: |
- # amd64
- go run build.go -goos linux -goarch amd64 -tags "${{env.TAGS}}" -cc "zig cc -target x86_64-linux-musl" -no-upgrade build ${{ matrix.pkg }}
- mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-amd64
- # arm64
- go run build.go -goos linux -goarch arm64 -tags "${{env.TAGS}}" -cc "zig cc -target aarch64-linux-musl" -no-upgrade build ${{ matrix.pkg }}
- mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-arm64
- # arm
- 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 }}
- mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-arm
- env:
- CGO_ENABLED: "1"
- BUILD_USER: docker
- EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
- - name: Login to GHCR
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Set version tags
- run: |
- version=${VERSION#v}
- repo=ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}
- ref="${{github.ref_name}}"
- ref=${ref//\//-} # slashes to dashes
- # List of tags for ghcr.io
- if [[ $version == @([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]) ]] ; then
- major=${version%.*.*}
- minor=${version%.*}
- tags=$repo:$version,$repo:$major,$repo:$minor,$repo:latest
- elif [[ $version == *-rc.@([0-9]|[0-9][0-9]) ]] ; then
- tags=$repo:$version,$repo:rc
- elif [[ $ref == "main" ]] ; then
- tags=$repo:edge
- else
- tags=$repo:$ref
- fi
- echo Pushing to $tags
- echo "DOCKER_TAGS=$tags" >> $GITHUB_ENV
- - name: Build and push Docker image
- uses: docker/build-push-action@v5
- with:
- context: .
- file: ${{ matrix.dockerfile }}
- platforms: linux/amd64,linux/arm64,linux/arm/7
- tags: ${{ env.DOCKER_TAGS }}
- push: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
- labels: |
- org.opencontainers.image.version=${{ env.VERSION }}
- org.opencontainers.image.revision=${{ github.sha }}
- #
- # Sync images to Docker hub. This takes the images already pushed to GHCR
- # and copies them to Docker hub. Runs for releases only.
- #
- docker-hub:
- name: Sync images to Docker hub
- 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'))
- runs-on: ubuntu-latest
- needs:
- - docker-ghcr
- environment: docker
- env:
- DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
- DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
- steps:
- - uses: actions/checkout@v4
- - name: Sync images
- uses: docker://docker.io/regclient/regsync:latest
- with:
- args:
- -c ./.github/regsync.yml
- once
- #
- # Check for known vulnerabilities in Go dependencies
- #
- govulncheck:
- runs-on: ubuntu-latest
- name: Run govulncheck
- needs:
- - facts
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: ${{ needs.facts.outputs.go-version }}
- cache: false
- - name: run govulncheck
- run: |
- go run build.go assets
- go install golang.org/x/vuln/cmd/govulncheck@latest
- govulncheck ./...
- #
- # golangci-lint runs a suite of static analysis checks on the code
- #
- golangci:
- runs-on: ubuntu-latest
- name: Run golangci-lint
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: 'stable'
- - name: ensure asset generation
- run: go run build.go assets
- - name: golangci-lint
- uses: golangci/golangci-lint-action@v8
- with:
- only-new-issues: true
- #
- # Meta checks for formatting, copyright, etc
- #
- meta:
- name: Run meta checks
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
- with:
- go-version: 'stable'
- - run: |
- go run build.go assets
- go test -v ./meta
|