---
# Github Actions build for rclone
# -*- compile-command: "yamllint -f parsable build.yml" -*-

name: build

# Trigger the workflow on push or pull request
on:
  push:
    branches:
      - '**'
    tags:
      - '**'
  pull_request:
  workflow_dispatch:
    inputs:
      manual:
        description: Manual run (bypass default conditions)
        type: boolean
        default: true

jobs:
  build:
    if: inputs.manual || (github.repository == 'rclone/rclone' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name))
    timeout-minutes: 60
    defaults:
      run:
        shell: bash
    strategy:
      fail-fast: false
      matrix:
        job_name: ['linux', 'linux_386', 'mac_amd64', 'mac_arm64', 'windows', 'other_os']

        include:
          - job_name: linux
            os: ubuntu-latest
            go: '~1.25.9'
            gotags: cmount
            build_flags: '-include "^linux/"'
            check: true
            quicktest: true
            racequicktest: true
            librclonetest: true
            deploy: true

          - job_name: linux_386
            os: ubuntu-latest
            go: '~1.25.9'
            goarch: 386
            gotags: cmount
            quicktest: true

          - job_name: mac_amd64
            os: macos-latest
            go: '~1.25.9'
            gotags: 'cmount'
            build_flags: '-include "^darwin/amd64" -cgo'
            quicktest: true
            racequicktest: true
            deploy: true

          - job_name: mac_arm64
            os: macos-latest
            go: '~1.25.9'
            gotags: 'cmount'
            build_flags: '-include "^darwin/arm64" -cgo -macos-arch arm64 -cgo-cflags=-I/usr/local/include -cgo-ldflags=-L/usr/local/lib'
            deploy: true

          - job_name: windows
            os: windows-latest
            go: '~1.25.9'
            gotags: cmount
            cgo: '0'
            build_flags: '-include "^windows/"'
            build_args: '-buildmode exe'
            quicktest: true
            deploy: true

          - job_name: other_os
            os: ubuntu-latest
            go: '~1.25.9'
            build_flags: '-exclude "^(windows/|darwin/|linux/)"'
            compile_all: true
            deploy: true

    name: ${{ matrix.job_name }}

    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Install Go
        uses: actions/setup-go@v6
        with:
          go-version: ${{ matrix.go }}
          check-latest: true

      - name: Set environment variables
        run: |
          echo 'GOTAGS=${{ matrix.gotags }}' >> $GITHUB_ENV
          echo 'BUILD_FLAGS=${{ matrix.build_flags }}' >> $GITHUB_ENV
          echo 'BUILD_ARGS=${{ matrix.build_args }}' >> $GITHUB_ENV
          if [[ "${{ matrix.goarch }}" != "" ]]; then echo 'GOARCH=${{ matrix.goarch }}' >> $GITHUB_ENV ; fi
          if [[ "${{ matrix.cgo }}" != "" ]]; then echo 'CGO_ENABLED=${{ matrix.cgo }}' >> $GITHUB_ENV ; fi

      - name: Install Libraries on Linux
        run: |
          sudo modprobe fuse
          sudo chmod 666 /dev/fuse
          sudo chown root:$USER /etc/fuse.conf
          sudo apt-get update
          sudo apt-get install -y fuse3 libfuse-dev rpm pkg-config git-annex git-annex-remote-rclone nfs-common
        if: matrix.os == 'ubuntu-latest'

      - name: Install Libraries on macOS
        run: |
          # https://github.com/Homebrew/brew/issues/15621#issuecomment-1619266788
          # https://github.com/orgs/Homebrew/discussions/4612#discussioncomment-6319008
          unset HOMEBREW_NO_INSTALL_FROM_API
          brew untap --force homebrew/core
          brew untap --force homebrew/cask
          brew update
          brew install --cask macfuse
          brew install git-annex git-annex-remote-rclone
        if: matrix.os == 'macos-latest'

      - name: Install Libraries on Windows
        shell: powershell
        run: |
          $ProgressPreference = 'SilentlyContinue'
          choco install -y winfsp zip
          echo "CPATH=C:\Program Files\WinFsp\inc\fuse;C:\Program Files (x86)\WinFsp\inc\fuse" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
          if ($env:GOARCH -eq "386") {
            choco install -y mingw --forcex86 --force
            echo "C:\\ProgramData\\chocolatey\\lib\\mingw\\tools\\install\\mingw32\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
          }
          # Copy mingw32-make.exe to make.exe so the same command line
          # can be used on Windows as on macOS and Linux
          $path = (get-command mingw32-make.exe).Path
          Copy-Item -Path $path -Destination (Join-Path (Split-Path -Path $path) 'make.exe')
        if: matrix.os == 'windows-latest'

      - name: Print Go version and environment
        run: |
          printf "Using go at: $(which go)\n"
          printf "Go version: $(go version)\n"
          printf "\n\nGo environment:\n\n"
          go env
          printf "\n\nRclone environment:\n\n"
          make vars
          printf "\n\nSystem environment:\n\n"
          env

      - name: Build rclone
        run: |
          make

      - name: Rclone version
        run: |
          rclone version

      - name: Run tests
        run: |
          make quicktest
        if: matrix.quicktest

      - name: Race test
        run: |
          make racequicktest
        if: matrix.racequicktest

      - name: Run librclone tests
        run: |
          make -C librclone/ctest test
          make -C librclone/ctest clean
          librclone/python/test_rclone.py
        if: matrix.librclonetest

      - name: Compile all architectures test
        run: |
          make
          make compile_all
        if: matrix.compile_all

      - name: Deploy built binaries
        run: |
          if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then make release_dep_linux ; fi
          make ci_beta
        env:
          RCLONE_CONFIG_PASS: ${{ secrets.RCLONE_CONFIG_PASS }}
        # working-directory: '$(modulePath)'
        # Deploy binaries if enabled in config && not a PR && not a fork
        if: env.RCLONE_CONFIG_PASS != '' && matrix.deploy && github.head_ref == '' && github.repository == 'rclone/rclone'

  lint:
    if: inputs.manual || (github.repository == 'rclone/rclone' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name))
    timeout-minutes: 30
    name: "lint"
    runs-on: ubuntu-latest

    steps:
      - name: Get runner parameters
        id: get-runner-parameters
        run: |
          echo "year-week=$(/bin/date -u "+%Y%V")" >> $GITHUB_OUTPUT
          echo "runner-os-version=$ImageOS" >> $GITHUB_OUTPUT

      - name: Checkout
        uses: actions/checkout@v6
        with:
            fetch-depth: 0

      - name: Install Go
        id: setup-go
        uses: actions/setup-go@v6
        with:
          go-version: '~1.25.9'
          check-latest: true
          cache: false

      - name: Cache
        uses: actions/cache@v5
        with:
          path: |
            ~/go/pkg/mod
            ~/.cache/go-build
            ~/.cache/golangci-lint
          key: golangci-lint-${{ steps.get-runner-parameters.outputs.runner-os-version }}-go${{ steps.setup-go.outputs.go-version }}-${{ steps.get-runner-parameters.outputs.year-week }}-${{ hashFiles('go.sum') }}
          restore-keys: golangci-lint-${{ steps.get-runner-parameters.outputs.runner-os-version }}-go${{ steps.setup-go.outputs.go-version }}-${{ steps.get-runner-parameters.outputs.year-week }}-

      - name: Code quality test (Linux)
        uses: golangci/golangci-lint-action@v9
        with:
          version: latest
          skip-cache: true

      - name: Code quality test (Windows)
        uses: golangci/golangci-lint-action@v9
        env:
          GOOS: "windows"
        with:
          version: latest
          skip-cache: true

      - name: Code quality test (macOS)
        uses: golangci/golangci-lint-action@v9
        env:
          GOOS: "darwin"
        with:
          version: latest
          skip-cache: true

      - name: Code quality test (FreeBSD)
        uses: golangci/golangci-lint-action@v9
        env:
          GOOS: "freebsd"
        with:
          version: latest
          skip-cache: true

      - name: Code quality test (OpenBSD)
        uses: golangci/golangci-lint-action@v9
        env:
          GOOS: "openbsd"
        with:
          version: latest
          skip-cache: true

      - name: Install govulncheck
        run: go install golang.org/x/vuln/cmd/govulncheck@latest

      - name: Scan for vulnerabilities
        run: govulncheck ./...

      - name: Check Markdown format
        uses: DavidAnson/markdownlint-cli2-action@v20
        with:
          globs: |
            CONTRIBUTING.md
            MAINTAINERS.md
            README.md
            RELEASE.md
            CODE_OF_CONDUCT.md
            librclone\README.md
            backend\s3\README.md
            docs/content/{_index,authors,bugs,changelog,docs,downloads,faq,filtering,gui,install,licence,overview,privacy}.md

      - name: Scan edits of autogenerated files
        run: bin/check_autogenerated_edits.py 'origin/${{ github.base_ref }}'
        if: github.event_name == 'pull_request'

  android:
    if: inputs.manual || (github.repository == 'rclone/rclone' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name))
    timeout-minutes: 30
    name: "android-all"
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      # Upgrade together with NDK version
      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version: '~1.25.9'

      - name: Set global environment variables
        run: |
          echo "VERSION=$(make version)" >> $GITHUB_ENV

      - name: build native rclone
        run: |
          make

      - name: install gomobile
        run: |
          go install golang.org/x/mobile/cmd/gobind@latest
          go install golang.org/x/mobile/cmd/gomobile@latest
          env PATH=$PATH:~/go/bin gomobile init
          echo "RCLONE_NDK_VERSION=21" >> $GITHUB_ENV

      - name: arm-v7a gomobile build
        run: env PATH=$PATH:~/go/bin gomobile bind -androidapi ${RCLONE_NDK_VERSION} -v -target=android/arm -javapkg=org.rclone -ldflags '-s -X github.com/rclone/rclone/fs.Version='${VERSION} github.com/rclone/rclone/librclone/gomobile

      - name: arm-v7a Set environment variables
        run: |
          echo "CC=$(echo $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi${RCLONE_NDK_VERSION}-clang)" >> $GITHUB_ENV
          echo "CC_FOR_TARGET=$CC" >> $GITHUB_ENV
          echo 'GOOS=android' >> $GITHUB_ENV
          echo 'GOARCH=arm' >> $GITHUB_ENV
          echo 'GOARM=7' >> $GITHUB_ENV
          echo 'CGO_ENABLED=1' >> $GITHUB_ENV
          echo 'CGO_LDFLAGS=-fuse-ld=lld -s -w' >> $GITHUB_ENV

      - name: arm-v7a build
        run: go build -v -tags android -trimpath -ldflags '-s -X github.com/rclone/rclone/fs.Version='${VERSION} -o build/rclone-android-${RCLONE_NDK_VERSION}-armv7a .

      - name: arm64-v8a Set environment variables
        run: |
          echo "CC=$(echo $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android${RCLONE_NDK_VERSION}-clang)" >> $GITHUB_ENV
          echo "CC_FOR_TARGET=$CC" >> $GITHUB_ENV
          echo 'GOOS=android' >> $GITHUB_ENV
          echo 'GOARCH=arm64' >> $GITHUB_ENV
          echo 'CGO_ENABLED=1' >> $GITHUB_ENV
          echo 'CGO_LDFLAGS=-fuse-ld=lld -s -w' >> $GITHUB_ENV

      - name: arm64-v8a build
        run: go build -v -tags android -trimpath -ldflags '-s -X github.com/rclone/rclone/fs.Version='${VERSION} -o build/rclone-android-${RCLONE_NDK_VERSION}-armv8a .

      - name: x86 Set environment variables
        run: |
          echo "CC=$(echo $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android${RCLONE_NDK_VERSION}-clang)" >> $GITHUB_ENV
          echo "CC_FOR_TARGET=$CC" >> $GITHUB_ENV
          echo 'GOOS=android' >> $GITHUB_ENV
          echo 'GOARCH=386' >> $GITHUB_ENV
          echo 'CGO_ENABLED=1' >> $GITHUB_ENV
          echo 'CGO_LDFLAGS=-fuse-ld=lld -s -w' >> $GITHUB_ENV

      - name: x86 build
        run: go build -v -tags android -trimpath -ldflags '-s -X github.com/rclone/rclone/fs.Version='${VERSION} -o build/rclone-android-${RCLONE_NDK_VERSION}-x86 .

      - name: x64 Set environment variables
        run: |
          echo "CC=$(echo $ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android${RCLONE_NDK_VERSION}-clang)" >> $GITHUB_ENV
          echo "CC_FOR_TARGET=$CC" >> $GITHUB_ENV
          echo 'GOOS=android' >> $GITHUB_ENV
          echo 'GOARCH=amd64' >> $GITHUB_ENV
          echo 'CGO_ENABLED=1' >> $GITHUB_ENV
          echo 'CGO_LDFLAGS=-fuse-ld=lld -s -w' >> $GITHUB_ENV

      - name: x64 build
        run: go build -v -tags android -trimpath -ldflags '-s -X github.com/rclone/rclone/fs.Version='${VERSION} -o build/rclone-android-${RCLONE_NDK_VERSION}-x64 .

      - name: Upload artifacts
        run: |
          make ci_upload
        env:
          RCLONE_CONFIG_PASS: ${{ secrets.RCLONE_CONFIG_PASS }}
        # Upload artifacts if not a PR && not a fork
        if: env.RCLONE_CONFIG_PASS != '' && github.head_ref == '' && github.repository == 'rclone/rclone'
