Make sure as much as possible runs for forks and PRs as well, while keeping the release specific stuff out of the way.
1112 lines
36 KiB
YAML
1112 lines
36 KiB
YAML
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:
|
|
|
|
#
|
|
# 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
|
|
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
|
|
|
|
- uses: mlugg/setup-zig@v2
|
|
|
|
- uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cache/go-build
|
|
~/go/pkg/mod
|
|
key: ${{ runner.os }}-go-${{ env.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 # 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/trusted-signing-action@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
|
|
runs-on: ubuntu-latest
|
|
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 actual Go version
|
|
run: |
|
|
go version
|
|
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
|
|
|
- uses: mlugg/setup-zig@v2
|
|
|
|
- uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cache/go-build
|
|
~/go/pkg/mod
|
|
key: ${{ runner.os }}-go-${{ env.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
|
|
env:
|
|
CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }}
|
|
runs-on: macos-latest
|
|
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 actual Go version
|
|
run: |
|
|
go version
|
|
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
|
|
|
- uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cache/go-build
|
|
~/go/pkg/mod
|
|
key: ${{ runner.os }}-go-${{ env.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
|
|
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 actual Go version
|
|
run: |
|
|
go version
|
|
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
|
|
|
- uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cache/go-build
|
|
~/go/pkg/mod
|
|
key: ${{ runner.os }}-go-${{ env.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
|
|
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: Package source
|
|
run: |
|
|
version=$(go run build.go version)
|
|
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
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
|
|
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
repository: syncthing/release-tools
|
|
path: tools
|
|
fetch-depth: 0
|
|
|
|
- name: Download artifacts
|
|
uses: actions/download-artifact@v4
|
|
|
|
- uses: actions/setup-go@v5
|
|
with:
|
|
go-version: ${{ env.GO_VERSION }}
|
|
cache: false
|
|
check-latest: true
|
|
|
|
- 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
|
|
|
|
version=$(go run build.go version)
|
|
echo "VERSION=$version" >> $GITHUB_ENV
|
|
|
|
- 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
|
|
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 actual Go version
|
|
run: |
|
|
go version
|
|
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
|
|
|
- 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-${{ env.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
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
repository: syncthing/release-tools
|
|
path: tools
|
|
fetch-depth: 0
|
|
|
|
- name: Download artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: packages-signed
|
|
path: packages
|
|
|
|
- uses: actions/setup-go@v5
|
|
with:
|
|
go-version: ${{ env.GO_VERSION }}
|
|
cache: false
|
|
check-latest: true
|
|
|
|
- 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 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
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
|
|
|
|
- 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: ${{ env.GO_VERSION }}
|
|
cache: false
|
|
check-latest: true
|
|
|
|
- name: Set version
|
|
run: |
|
|
version=$(go run build.go version)
|
|
echo "VERSION=$version" >> $GITHUB_ENV
|
|
|
|
- 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 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 objstore:release/${{ env.VERSION }} objstore:release/latest
|
|
|
|
- name: Create GitHub release 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 "$VERSION" \
|
|
packages/*.asc packages/*.json \
|
|
packages/syncthing-*.tar.gz \
|
|
packages/syncthing-*.zip \
|
|
packages/syncthing*.deb
|
|
env:
|
|
GH_TOKEN: ${{ secrets.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
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
|
|
|
|
- name: Download packages
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: debian-packages
|
|
path: packages
|
|
|
|
- name: Set version
|
|
run: |
|
|
version=$(go run build.go version)
|
|
echo "Version: $version"
|
|
echo "VERSION=$version" >> $GITHUB_ENV
|
|
|
|
# Decide whether packages should go to stable, candidate or nightly
|
|
- name: Prepare packages
|
|
run: |
|
|
kind=stable
|
|
if [[ $VERSION == v2* ]] ; then
|
|
kind=v2
|
|
elif [[ $VERSION == *-rc.[0-9] ]] ; then
|
|
kind=candidate
|
|
elif [[ $VERSION == *-* ]] ; then
|
|
kind=nightly
|
|
fi
|
|
echo "Kind: $kind"
|
|
mkdir -p packages/syncthing/$kind
|
|
mv packages/*.deb packages/syncthing/$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 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
|
|
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
|
|
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 actual Go version
|
|
run: |
|
|
go version
|
|
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
|
|
|
- uses: mlugg/setup-zig@v2
|
|
|
|
- uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.cache/go-build
|
|
~/go/pkg/mod
|
|
key: ${{ runner.os }}-go-${{ env.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=$(go run build.go version)
|
|
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
|
|
echo "VERSION=$version" >> $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
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-go@v5
|
|
with:
|
|
go-version: ${{ env.GO_VERSION }}
|
|
cache: false
|
|
check-latest: true
|
|
|
|
- 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
|