diff --git a/.github/workflows/build-infra-dockers.yaml b/.github/workflows/build-infra-dockers.yaml deleted file mode 100644 index 85284a1a1..000000000 --- a/.github/workflows/build-infra-dockers.yaml +++ /dev/null @@ -1,88 +0,0 @@ -name: Build Infrastructure Images - -on: - push: - branches: - - infrastructure - - infra-* - -env: - GO_VERSION: "~1.26.0" - CGO_ENABLED: "0" - BUILD_USER: docker - BUILD_HOST: github.syncthing.net - -permissions: - contents: read - packages: write - -jobs: - docker-syncthing: - name: Build and push Docker images - if: github.repository_owner == 'syncthing' - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - pkg: - - stcrashreceiver - - strelaypoolsrv - - stupgrades - - ursrv - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - uses: actions/setup-go@v6 - with: - go-version: ${{ env.GO_VERSION }} - check-latest: true - - - name: Login to Docker Hub - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Login to GHCR - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build binaries - run: | - for arch in arm64 amd64; do - go run build.go -goos linux -goarch "$arch" build ${{ matrix.pkg }} - mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-"$arch" - done - - - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - - - name: Set Docker tags (all branches) - run: | - tags=docker.io/syncthing/${{ matrix.pkg }}:${{ github.sha }},ghcr.io/syncthing/infra/${{ matrix.pkg }}:${{ github.sha }} - echo "TAGS=$tags" >> $GITHUB_ENV - - - name: Set Docker tags (latest) - if: github.ref == 'refs/heads/infrastructure' - run: | - tags=docker.io/syncthing/${{ matrix.pkg }}:latest,ghcr.io/syncthing/infra/${{ matrix.pkg }}:latest,${{ env.TAGS }} - echo "TAGS=$tags" >> $GITHUB_ENV - - - name: Build and push - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 - with: - context: . - file: ./Dockerfile.${{ matrix.pkg }} - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.TAGS }} - labels: | - org.opencontainers.image.revision=${{ github.sha }} diff --git a/.github/workflows/build-syncthing.yaml b/.github/workflows/build-syncthing.yaml deleted file mode 100644 index 1cc4ba6a3..000000000 --- a/.github/workflows/build-syncthing.yaml +++ /dev/null @@ -1,1212 +0,0 @@ -name: Build Syncthing - -on: - pull_request: - push: - branches-ignore: - - release - - release-rc* - workflow_call: - workflow_dispatch: - -permissions: - contents: read - issues: read - pull-requests: read - -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.26.0" - - # Optimize compatibility on the slow architectures. - 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: "sqlite_omit_load_extension sqlite_dbstat" - TAGS_LINUX: "sqlite_omit_load_extension sqlite_dbstat netgo osusergo" - -# 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 }} - release-generation: ${{ steps.get-version.outputs.release-generation }} - go-version: ${{ steps.get-go.outputs.go-version }} - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882 - - - uses: actions/setup-go@v6 - 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" - - generation=v1 - if [[ $version == v2.* ]] ; then - generation=v2 - fi - echo "release-generation=$generation" >> "$GITHUB_OUTPUT" - echo "Release generation: $generation" - - 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.25.0", "~1.26.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@v5 - - - uses: actions/setup-go@v6 - 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-illumos - - package-cross - - package-source - - package-debian - - package-windows - - govulncheck - - golangci - - meta - steps: - - uses: actions/checkout@v5 - - # - # 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@v5 - - - uses: actions/setup-go@v6 - with: - go-version: ${{ needs.facts.outputs.go-version }} - cache: false - - - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # 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/goversioninfo@v1.4.0 - - - 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 # fails 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')) - runs-on: windows-latest - needs: - - package-windows - steps: - - name: Download artifacts - uses: actions/download-artifact@v7 - 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/trusted-signing-action@0d74250c661747df006298d0fb49944c10f16e03 # v0.5.1 - 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 (${{ matrix.group }}) - runs-on: ubuntu-latest - needs: - - facts - strategy: - fail-fast: false - # split the build into three groups with roughtly the same amount of - # work, in order to reduce wall clock time - matrix: - include: - - group: common - targets: | - amd64 zig cc -target x86_64-linux-musl - 386 zig cc -target x86-linux-musl - arm zig cc -target arm-linux-musleabi -mcpu=arm1136j_s - arm64 zig cc -target aarch64-linux-musl - extra-packages: "" - - group: mips - targets: | - mips zig cc -target mips-linux-musleabi - mipsle zig cc -target mipsel-linux-musleabi - mips64 mips64-linux-gnuabi64-gcc - mips64le mips64el-linux-gnuabi64-gcc - extra-packages: "gcc-mips64-linux-gnuabi64 gcc-mips64el-linux-gnuabi64" - - group: other - targets: | - riscv64 zig cc -target riscv64-linux-musl - s390x zig cc -target s390x-linux-musl - loong64 zig cc -target loongarch64-linux-musl - ppc64le zig cc -target powerpc64le-linux-musl - extra-packages: "" - env: - VERSION: ${{ needs.facts.outputs.version }} - RELEASE_KIND: ${{ needs.facts.outputs.release-kind }} - steps: - - uses: actions/checkout@v5 - - - uses: actions/setup-go@v6 - with: - go-version: ${{ needs.facts.outputs.go-version }} - cache: false - - - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 - - - uses: actions/cache@v4 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-package-linux-${{ matrix.group }}-${{ hashFiles('go.sum') }} - - - name: Install extra packages - if: matrix.extra-packages != '' - run: sudo apt-get install -y ${{ matrix.extra-packages }} - - - name: Create packages - run: | - echo "$TARGETS" | while read -r arch cc; do - [ -z "$arch" ] && continue - for tgt in syncthing stdiscosrv strelaysrv ; do - go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch "$arch" -cc "$cc" tar "$tgt" - done - done - env: - CGO_ENABLED: "1" - EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static" - TARGETS: ${{ matrix.targets }} - - - name: Archive artifacts - uses: actions/upload-artifact@v4 - with: - name: packages-linux-${{ matrix.group }} - path: | - *.tar.gz - compat.json - - package-illumos: - runs-on: ubuntu-latest - name: Package for illumos - needs: - - facts - env: - VERSION: ${{ needs.facts.outputs.version }} - GO_VERSION: ${{ needs.facts.outputs.go-version }} - steps: - - uses: actions/checkout@v5 - - - name: Build syncthing in OmniOS VM - uses: vmactions/omnios-vm@68da93c6d9812b29fc90c5b5141b093f84a590fb # v1 - with: - envs: "VERSION GO_VERSION CGO_ENABLED" - usesh: true - prepare: | - pkg install developer/gcc14 web/curl archiver/gnu-tar - run: | - curl -L "https://go.dev/dl/go$GO_VERSION.illumos-amd64.tar.gz" | gtar xzf - - export PATH="$GITHUB_WORKSPACE/go/bin:$PATH" - go version - for tgt in syncthing stdiscosrv strelaysrv ; do - go run build.go -tags "${{env.TAGS}}" tar "$tgt" - done - env: - CGO_ENABLED: "1" - - - name: Archive artifacts - uses: actions/upload-artifact@v4 - with: - name: packages-illumos - path: "*.tar.gz" - # - # 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')) - 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@v5 - - - uses: actions/setup-go@v6 - 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 < 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')) - needs: - - package-macos - runs-on: macos-latest - steps: - - name: Download artifacts - uses: actions/download-artifact@v7 - 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@v5 - - - uses: actions/setup-go@v6 - 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 illumos/ \ - | 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@v5 - - - uses: actions/setup-go@v6 - 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')) - needs: - - codesign-windows - - package-linux - - package-illumos - - 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@v5 - - - uses: actions/checkout@v5 - with: - repository: syncthing/release-tools - path: tools - - - name: Download artifacts - uses: actions/download-artifact@v7 - with: - pattern: packages-* - path: packages - merge-multiple: true - - - uses: actions/setup-go@v6 - 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" - 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@v5 - - - uses: actions/setup-go@v6 - with: - go-version: ${{ needs.facts.outputs.go-version }} - cache: false - - - uses: ruby/setup-ruby@eab2afb99481ca09a4e91171a8e0aee0e89bfedd # v1 - with: - ruby-version: '3.0' - - - name: Install fpm - run: | - gem install fpm - - - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # 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_LINUX}}" -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_LINUX}}" -goos linux -goarch armel -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" deb "$tgt" - go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS_LINUX}}" -goos linux -goarch armhf -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" deb "$tgt" - go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS_LINUX}}" -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') - needs: - - sign-for-upgrade - - facts - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - with: - repository: syncthing/release-tools - path: tools - - - name: Download artifacts - uses: actions/download-artifact@v7 - with: - name: packages-signed - path: packages - - - uses: actions/setup-go@v6 - 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')) - permissions: - contents: write - id-token: write - attestations: write - artifact-metadata: 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@v5 - with: - fetch-depth: 0 - ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882 - - - name: Download signed packages - uses: actions/download-artifact@v7 - with: - name: packages-signed - path: packages - - - name: Download debian packages - uses: actions/download-artifact@v7 - with: - name: debian-packages - path: packages - - - name: Create GitHub build provenance attestations - uses: actions/attest-build-provenance@v3 - with: - subject-path: packages/* - - - 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 \ - --draft \ - --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 - gh release edit "$VERSION" --draft=false - - 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 \ - --draft \ - --title "$VERSION" \ - --notes "https://github.com/syncthing/syncthing/releases/tag/$VERSION" - fi - gh release upload --clobber "$VERSION" \ - $PKGS/*.asc \ - $PKGS/*${repo}* - gh release edit "$VERSION" --draft=false - 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')) - needs: - - package-debian - - facts - env: - VERSION: ${{ needs.facts.outputs.version }} - RELEASE_KIND: ${{ needs.facts.outputs.release-kind }} - RELEASE_GENERATION: ${{ needs.facts.outputs.release-generation }} - runs-on: ubuntu-latest - steps: - - name: Download packages - uses: actions/download-artifact@v7 - with: - name: debian-packages - path: packages - - # Decide whether packages should go to stable, candidate or nightly - - 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 apt - - - name: Prepare packages - run: | - sudo chown -R $(id -u) apt/pool - mv -n packages/*.deb apt/pool - - - name: Update archive - uses: docker://ghcr.io/kastelo/ezapt:latest - with: - args: - publish --root apt - 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 apt objstore:apt - - # - # 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: - fail-fast: false - 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@v5 - - - uses: actions/setup-go@v6 - with: - go-version: ${{ needs.facts.outputs.go-version }} - cache: false - - - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # 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: | - mkdir bin - - # amd64 - go run build.go -goos linux -goarch amd64 -tags "${{env.TAGS_LINUX}}" -cc "zig cc -target x86_64-linux-musl" -no-upgrade build ${{ matrix.pkg }} - mv ${{ matrix.pkg }} bin/${{ matrix.pkg }}-linux-amd64 - - # arm64 - go run build.go -goos linux -goarch arm64 -tags "${{env.TAGS_LINUX}}" -cc "zig cc -target aarch64-linux-musl" -no-upgrade build ${{ matrix.pkg }} - mv ${{ matrix.pkg }} bin/${{ matrix.pkg }}-linux-arm64 - - # arm - go run build.go -goos linux -goarch arm -tags "${{env.TAGS_LINUX}}" -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" -no-upgrade build ${{ matrix.pkg }} - mv ${{ matrix.pkg }} bin/${{ 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@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - - - name: Set version tags - run: | - version=${VERSION#v} - repo=ghcr.io/${{ github.repository_owner }}/${{ matrix.image }} - ref="${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 - env: - REF_NAME: ${{github.ref_name}} - - - name: Prepare context dir - run: | - mkdir ctx - mv bin/* script ctx - - - name: Build and push Docker image - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 - with: - context: ctx - 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 - env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - steps: - - uses: actions/checkout@v5 - - 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@v5 - - - uses: actions/setup-go@v6 - 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 - if: github.event_name == 'pull_request' - steps: - - uses: actions/checkout@v5 - - uses: actions/setup-go@v6 - with: - go-version: 'stable' - - - name: ensure asset generation - run: go run build.go assets - - - name: golangci-lint - uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # 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@v5 - - uses: actions/setup-go@v6 - with: - go-version: 'stable' - - - run: | - go run build.go assets - go test -v ./meta diff --git a/.github/workflows/mirrors.yaml b/.github/workflows/mirrors.yaml deleted file mode 100644 index c5f9aabe4..000000000 --- a/.github/workflows/mirrors.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: Mirrors - -on: [push, delete] - -permissions: - contents: read - -jobs: - codeberg: - name: Mirror to Codeberg - if: github.repository_owner == 'syncthing' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: yesolutions/mirror-action@662fce0eced8996f64d7fa264d76cddd84827f33 # master - with: - REMOTE: ssh://git@codeberg.org/${{ github.repository }}.git - GIT_SSH_PRIVATE_KEY: ${{ secrets.CODEBERG_PUSH_KEY }} - GIT_SSH_NO_VERIFY_HOST: "true" diff --git a/.github/workflows/org-members.yaml b/.github/workflows/org-members.yaml deleted file mode 100644 index 071265674..000000000 --- a/.github/workflows/org-members.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: Org membership recommendations - -on: - workflow_dispatch: - schedule: - - cron: '0 0 1 * *' - -jobs: - - run-recommendation: - name: Check for a recommendation - if: github.repository_owner == 'syncthing' - runs-on: ubuntu-latest - steps: - - - uses: docker://ghcr.io/calmh/github-org-members:latest - env: - GITHUB_ORGANISATION: syncthing - GITHUB_TOKEN: ${{ secrets.GOM_GITHUB_TOKEN }} - GOM_IGNORE_USERS: ${{ secrets.GOM_IGNORE_USERS }} - GOM_ALSO_REPOS: ${{ secrets.GOM_ALSO_REPOS }} diff --git a/.github/workflows/pr-metadata.yaml b/.github/workflows/pr-metadata.yaml deleted file mode 100644 index 8f403db9e..000000000 --- a/.github/workflows/pr-metadata.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: PR metadata - -on: - pull_request_target: - types: - - opened - - reopened - - edited - - synchronize - -permissions: - contents: read - pull-requests: write - -jobs: - - # - # Set labels on PRs, which are then used to categorise release notes - # - - labels: - name: Set labels - if: github.repository_owner == 'syncthing' - runs-on: ubuntu-latest - steps: - - uses: srvaroa/labeler@9c29ad1ef33d169f9ef33c52722faf47a566bcf3 # v1 - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/release-syncthing.yaml b/.github/workflows/release-syncthing.yaml deleted file mode 100644 index 3970341de..000000000 --- a/.github/workflows/release-syncthing.yaml +++ /dev/null @@ -1,60 +0,0 @@ -name: Release Syncthing - -on: - push: - branches: - - release - - release-rc* - -permissions: - contents: write - -jobs: - create-release-tag: - name: Create release tag - if: github.repository_owner == 'syncthing' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882 - token: ${{ secrets.ACTIONS_GITHUB_TOKEN }} - - - uses: actions/setup-go@v6 - with: - go-version: stable - - - name: Determine version to release - run: | - if [[ "$GITHUB_REF_NAME" == "release" ]] ; then - next=$(go run ./script/next-version.go) - else - next=$(go run ./script/next-version.go --pre) - fi - echo "NEXT=$next" >> $GITHUB_ENV - echo "Next version is $next" - - prev=$(git describe --exclude "*-*" --abbrev=0) - echo "PREV=$prev" >> $GITHUB_ENV - echo "Previous version is $prev" - - - name: Determine release notes - run: | - go run ./script/relnotes.go --new-ver "$NEXT" --branch "$GITHUB_REF_NAME" --prev-ver "$PREV" > notes.md - env: - GITHUB_TOKEN: ${{ secrets.ACTIONS_GITHUB_TOKEN }} - - - name: Create and push tag - run: | - git config --global user.name 'Syncthing Release Automation' - git config --global user.email 'release@syncthing.net' - git tag -a -F notes.md --cleanup=whitespace "$NEXT" - git push origin "$NEXT" - - - name: Trigger the build - uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1 - with: - workflow: build-syncthing.yaml - ref: refs/tags/${{ env.NEXT }} - token: ${{ secrets.ACTIONS_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-nightly.yaml b/.github/workflows/trigger-nightly.yaml deleted file mode 100644 index 82b513300..000000000 --- a/.github/workflows/trigger-nightly.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Trigger nightly build & release -on: - workflow_dispatch: - schedule: - # Run nightly build at 01:00 UTC - - cron: '00 01 * * *' - -permissions: - contents: write - -jobs: - - trigger-nightly: - name: Push to release-nightly to trigger build - if: github.repository_owner == 'syncthing' - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v5 - with: - token: ${{ secrets.ACTIONS_GITHUB_TOKEN }} - fetch-depth: 0 - - - run: | - git push origin main:release-nightly diff --git a/.github/workflows/update-docs-translations.yaml b/.github/workflows/update-docs-translations.yaml deleted file mode 100644 index 8a69537d1..000000000 --- a/.github/workflows/update-docs-translations.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: Update translations and documentation -on: - workflow_dispatch: - schedule: - - cron: '42 3 * * 1' - -permissions: - contents: write - -jobs: - - update_transifex_docs: - runs-on: ubuntu-latest - name: Update translations and documentation - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - token: ${{ secrets.ACTIONS_GITHUB_TOKEN }} - - uses: actions/setup-go@v6 - with: - go-version: stable - - run: | - set -euo pipefail - git config --global user.name 'Syncthing Release Automation' - git config --global user.email 'release@syncthing.net' - bash build.sh translate - bash build.sh prerelease - git push - env: - WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }} diff --git a/gui/default/index.html b/gui/default/index.html index e3e573c9a..3e060b5a9 100644 --- a/gui/default/index.html +++ b/gui/default/index.html @@ -1017,6 +1017,9 @@ + diff --git a/lib/api/auto/custom_marker_test.go b/lib/api/auto/custom_marker_test.go new file mode 100644 index 000000000..71c382e50 --- /dev/null +++ b/lib/api/auto/custom_marker_test.go @@ -0,0 +1,42 @@ +// Copyright (C) 2026 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package auto + +import ( + "compress/gzip" + "io" + "strings" + "testing" +) + +const customBuildMarker = "It syncs .stignore now!" + +func TestCustomBuildMarkerIsEmbedded(t *testing.T) { + asset, ok := Assets()["default/index.html"] + if !ok { + t.Fatal("default/index.html is missing from embedded GUI assets") + } + + content := asset.Content + if asset.Gzipped { + reader, err := gzip.NewReader(strings.NewReader(asset.Content)) + if err != nil { + t.Fatal(err) + } + defer reader.Close() + + data, err := io.ReadAll(reader) + if err != nil { + t.Fatal(err) + } + content = string(data) + } + + if !strings.Contains(content, customBuildMarker) { + t.Fatalf("embedded GUI assets do not contain custom build marker %q", customBuildMarker) + } +} diff --git a/lib/fs/filesystem.go b/lib/fs/filesystem.go index 31bbb9770..dcece778e 100644 --- a/lib/fs/filesystem.go +++ b/lib/fs/filesystem.go @@ -284,8 +284,8 @@ func NewFilesystem(fsType FilesystemType, uri string, opts ...Option) Filesystem } // fs cannot import config or versioner, so we hard code .stfolder -// (config.DefaultMarkerName) and .stversions (versioner.DefaultPath) -var internals = []string{".stfolder", ".stignore", ".stversions"} +// (config.DefaultMarkerName) and .stversions (versioner.DefaultPath). +var internals = []string{".stfolder", ".stversions"} // IsInternal returns true if the file, as a path relative to the folder // root, represents an internal file that should always be ignored. The file diff --git a/lib/fs/filesystem_test.go b/lib/fs/filesystem_test.go index 08e45ff50..2d100a2b0 100644 --- a/lib/fs/filesystem_test.go +++ b/lib/fs/filesystem_test.go @@ -21,10 +21,8 @@ func TestIsInternal(t *testing.T) { internal bool }{ {".stfolder", true}, - {".stignore", true}, {".stversions", true}, {".stfolder/foo", true}, - {".stignore/foo", true}, {".stversions/foo", true}, {".stfolderfoo", false}, @@ -34,6 +32,8 @@ func TestIsInternal(t *testing.T) { {"foo.stignore", false}, {"foo.stversions", false}, {"foo/.stfolder", false}, + {".stignore", false}, + {".stignore/foo", false}, {"foo/.stignore", false}, {"foo/.stversions", false}, } diff --git a/lib/model/folder_recvonly_test.go b/lib/model/folder_recvonly_test.go index 12916127f..2feea65c1 100644 --- a/lib/model/folder_recvonly_test.go +++ b/lib/model/folder_recvonly_test.go @@ -60,15 +60,15 @@ func TestRecvOnlyRevertDeletes(t *testing.T) { must(t, m.ScanFolder("ro")) - // We should now have two files and two directories, with global state unchanged. + // We should now have three files and two directories, with global state unchanged. size = mustV(m.GlobalSize("ro")) if size.Files != 1 || size.Directories != 1 { t.Fatalf("Global: expected 1 file and 1 directory: %+v", size) } size = mustV(m.LocalSize("ro", protocol.LocalDeviceID)) - if size.Files != 2 || size.Directories != 2 { - t.Fatalf("Local: expected 2 files and 2 directories: %+v", size) + if size.Files != 3 || size.Directories != 2 { + t.Fatalf("Local: expected 3 files and 2 directories: %+v", size) } size = mustV(m.ReceiveOnlySize("ro")) if size.Files+size.Directories == 0 { diff --git a/lib/model/requests_test.go b/lib/model/requests_test.go index 288140721..6f8124e97 100644 --- a/lib/model/requests_test.go +++ b/lib/model/requests_test.go @@ -974,13 +974,15 @@ func TestIgnoreDeleteUnignore(t *testing.T) { file := "foobar" contents := []byte("test file contents\n") - basicCheck := func(fs []protocol.FileInfo) { + basicCheck := func(fs []protocol.FileInfo) protocol.FileInfo { t.Helper() - if len(fs) != 1 { - t.Fatal("expected a single index entry, got", len(fs)) - } else if fs[0].Name != file { - t.Fatalf("expected a index entry for %v, got one for %v", file, fs[0].Name) + for _, f := range fs { + if f.Name == file { + return f + } } + t.Fatalf("expected an index entry for %v, got %v", file, fs) + return protocol.FileInfo{} } done := make(chan struct{}) @@ -1001,8 +1003,7 @@ func TestIgnoreDeleteUnignore(t *testing.T) { done = make(chan struct{}) fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error { - basicCheck(fs) - f := fs[0] + f := basicCheck(fs) if !f.IsInvalid() { t.Errorf("Received non-invalid index update") } @@ -1022,8 +1023,7 @@ func TestIgnoreDeleteUnignore(t *testing.T) { done = make(chan struct{}) fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error { - basicCheck(fs) - f := fs[0] + f := basicCheck(fs) if f.IsInvalid() { t.Errorf("Received invalid index update") } diff --git a/lib/scanner/walk_test.go b/lib/scanner/walk_test.go index 699772f97..331c2fbfa 100644 --- a/lib/scanner/walk_test.go +++ b/lib/scanner/walk_test.go @@ -40,6 +40,7 @@ type testfile struct { type testfileList []testfile var testdata = testfileList{ + {".stignore", 48, "f60db5c36f642f8a6c1a636024330cd4dba6ab965083542f3629ff7d8c547911"}, {"afile", 4, "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"}, {"dir1", 0, ""}, {filepath.Join("dir1", "dfile"), 5, "49ae93732fcf8d63fe1cce759664982dbd5b23161f007dba8561862adc96d063"},