name: test on: # run tests on push to master, but not when other branches are pushed to push: branches: - master # run tests for all pull requests pull_request: merge_group: permissions: contents: read env: latest_go: "1.22.x" GO111MODULE: on jobs: test: strategy: matrix: # list of jobs to run: include: - job_name: Windows go: 1.22.x os: windows-latest - job_name: macOS go: 1.22.x os: macOS-latest test_fuse: false - job_name: Linux go: 1.22.x os: ubuntu-latest test_cloud_backends: true test_fuse: true check_changelog: true - job_name: Linux (race) go: 1.22.x os: ubuntu-latest test_fuse: true test_opts: "-race" - job_name: Linux go: 1.21.x os: ubuntu-latest test_fuse: true - job_name: Linux go: 1.20.x os: ubuntu-latest test_fuse: true - job_name: Linux go: 1.19.x os: ubuntu-latest test_fuse: true name: ${{ matrix.job_name }} Go ${{ matrix.go }} runs-on: ${{ matrix.os }} env: GOPROXY: https://proxy.golang.org steps: - name: Set up Go ${{ matrix.go }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.go }} - name: Get programs (Linux/macOS) run: | echo "build Go tools" go install github.com/restic/rest-server/cmd/rest-server@master echo "install minio server" mkdir $HOME/bin if [ "$RUNNER_OS" == "macOS" ]; then wget --no-verbose -O $HOME/bin/minio https://dl.minio.io/server/minio/release/darwin-amd64/minio else wget --no-verbose -O $HOME/bin/minio https://dl.minio.io/server/minio/release/linux-amd64/minio fi chmod 755 $HOME/bin/minio echo "install rclone" if [ "$RUNNER_OS" == "macOS" ]; then wget --no-verbose -O rclone.zip https://downloads.rclone.org/rclone-current-osx-amd64.zip else wget --no-verbose -O rclone.zip https://downloads.rclone.org/rclone-current-linux-amd64.zip fi unzip rclone.zip cp rclone*/rclone $HOME/bin chmod 755 $HOME/bin/rclone rm -rf rclone* # add $HOME/bin to path ($GOBIN was already added to the path by setup-go@v3) echo $HOME/bin >> $GITHUB_PATH if: matrix.os == 'ubuntu-latest' || matrix.os == 'macOS-latest' - name: Get programs (Windows) shell: powershell run: | $ProgressPreference = 'SilentlyContinue' echo "build Go tools" go install github.com/restic/rest-server/cmd/rest-server@master echo "install minio server" mkdir $Env:USERPROFILE/bin Invoke-WebRequest https://dl.minio.io/server/minio/release/windows-amd64/minio.exe -OutFile $Env:USERPROFILE/bin/minio.exe echo "install rclone" Invoke-WebRequest https://downloads.rclone.org/rclone-current-windows-amd64.zip -OutFile rclone.zip unzip rclone.zip copy rclone*/rclone.exe $Env:USERPROFILE/bin # add $USERPROFILE/bin to path ($GOBIN was already added to the path by setup-go@v3) echo $Env:USERPROFILE\bin >> $Env:GITHUB_PATH echo "install tar" cd $env:USERPROFILE mkdir tar cd tar # install exactly these versions of tar and the libraries, other combinations might not work! Invoke-WebRequest https://github.com/restic/test-assets/raw/master/tar-1.13-1-bin.zip -OutFile tar.zip unzip tar.zip Invoke-WebRequest https://github.com/restic/test-assets/raw/master/libintl-0.11.5-2-bin.zip -OutFile libintl.zip unzip libintl.zip Invoke-WebRequest https://github.com/restic/test-assets/raw/master/libiconv-1.8-1-bin.zip -OutFile libiconv.zip unzip libiconv.zip # add $USERPROFILE/tar/bin to path echo $Env:USERPROFILE\tar\bin >> $Env:GITHUB_PATH if: matrix.os == 'windows-latest' - name: Check out code uses: actions/checkout@v4 - name: Build with build.go run: | go run build.go - name: Minimal test run: | ./restic init ./restic backup . env: RESTIC_REPOSITORY: ../testrepo RESTIC_PASSWORD: password - name: Run local Tests env: RESTIC_TEST_FUSE: ${{ matrix.test_fuse }} run: | go test -cover ${{matrix.test_opts}} ./... - name: Test cloud backends env: RESTIC_TEST_S3_KEY: ${{ secrets.RESTIC_TEST_S3_KEY }} RESTIC_TEST_S3_SECRET: ${{ secrets.RESTIC_TEST_S3_SECRET }} RESTIC_TEST_S3_REPOSITORY: ${{ secrets.RESTIC_TEST_S3_REPOSITORY }} RESTIC_TEST_AZURE_ACCOUNT_NAME: ${{ secrets.RESTIC_TEST_AZURE_ACCOUNT_NAME }} RESTIC_TEST_AZURE_ACCOUNT_KEY: ${{ secrets.RESTIC_TEST_AZURE_ACCOUNT_KEY }} RESTIC_TEST_AZURE_REPOSITORY: ${{ secrets.RESTIC_TEST_AZURE_REPOSITORY }} RESTIC_TEST_B2_ACCOUNT_ID: ${{ secrets.RESTIC_TEST_B2_ACCOUNT_ID }} RESTIC_TEST_B2_ACCOUNT_KEY: ${{ secrets.RESTIC_TEST_B2_ACCOUNT_KEY }} RESTIC_TEST_B2_REPOSITORY: ${{ secrets.RESTIC_TEST_B2_REPOSITORY }} RESTIC_TEST_GS_REPOSITORY: ${{ secrets.RESTIC_TEST_GS_REPOSITORY }} RESTIC_TEST_GS_PROJECT_ID: ${{ secrets.RESTIC_TEST_GS_PROJECT_ID }} GOOGLE_PROJECT_ID: ${{ secrets.RESTIC_TEST_GS_PROJECT_ID }} RESTIC_TEST_GS_APPLICATION_CREDENTIALS_B64: ${{ secrets.RESTIC_TEST_GS_APPLICATION_CREDENTIALS_B64 }} RESTIC_TEST_OS_AUTH_URL: ${{ secrets.RESTIC_TEST_OS_AUTH_URL }} RESTIC_TEST_OS_TENANT_NAME: ${{ secrets.RESTIC_TEST_OS_TENANT_NAME }} RESTIC_TEST_OS_USERNAME: ${{ secrets.RESTIC_TEST_OS_USERNAME }} RESTIC_TEST_OS_PASSWORD: ${{ secrets.RESTIC_TEST_OS_PASSWORD }} RESTIC_TEST_OS_REGION_NAME: ${{ secrets.RESTIC_TEST_OS_REGION_NAME }} RESTIC_TEST_SWIFT: ${{ secrets.RESTIC_TEST_SWIFT }} # fail if any of the following tests cannot be run RESTIC_TEST_DISALLOW_SKIP: "restic/backend/rest.TestBackendREST,\ restic/backend/sftp.TestBackendSFTP,\ restic/backend/s3.TestBackendMinio,\ restic/backend/rclone.TestBackendRclone,\ restic/backend/s3.TestBackendS3,\ restic/backend/swift.TestBackendSwift,\ restic/backend/b2.TestBackendB2,\ restic/backend/gs.TestBackendGS,\ restic/backend/azure.TestBackendAzure" run: | # prepare credentials for Google Cloud Storage tests in a temp file export GOOGLE_APPLICATION_CREDENTIALS=$(mktemp --tmpdir restic-gcs-auth-XXXXXXX) echo $RESTIC_TEST_GS_APPLICATION_CREDENTIALS_B64 | base64 -d > $GOOGLE_APPLICATION_CREDENTIALS go test -cover -parallel 4 ./internal/backend/... # only run cloud backend tests for pull requests from and pushes to our # own repo, otherwise the secrets are not available # Skip for Dependabot pull requests as these are run without secrets # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions#responding-to-events if: ((github.repository == 'restic/restic' && github.event_name == 'push') || github.event.pull_request.head.repo.full_name == github.repository) && (github.actor != 'dependabot[bot]') && matrix.test_cloud_backends - name: Check changelog files with calens run: | echo "install calens" go install github.com/restic/calens@latest echo "check changelog files" calens if: matrix.check_changelog cross_compile: strategy: matrix: # run cross-compile in three batches parallel so the overall tests run faster subset: - "0/3" - "1/3" - "2/3" env: GOPROXY: https://proxy.golang.org runs-on: ubuntu-latest name: Cross Compile for subset ${{ matrix.subset }} steps: - name: Set up Go ${{ env.latest_go }} uses: actions/setup-go@v5 with: go-version: ${{ env.latest_go }} - name: Check out code uses: actions/checkout@v4 - name: Cross-compile for subset ${{ matrix.subset }} run: | mkdir build-output build-output-debug go run ./helpers/build-release-binaries/main.go -o build-output -s . --platform-subset ${{ matrix.subset }} go run ./helpers/build-release-binaries/main.go -o build-output-debug -s . --platform-subset ${{ matrix.subset }} --tags debug lint: name: lint runs-on: ubuntu-latest permissions: contents: read # allow annotating code in the PR checks: write steps: - name: Set up Go ${{ env.latest_go }} uses: actions/setup-go@v5 with: go-version: ${{ env.latest_go }} - name: Check out code uses: actions/checkout@v4 - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. version: v1.57.1 args: --verbose --timeout 5m # only run golangci-lint for pull requests, otherwise ALL hints get # reported. We need to slowly address all issues until we can enable # linting the master branch :) if: github.event_name == 'pull_request' - name: Check go.mod/go.sum run: | echo "check if go.mod and go.sum are up to date" go mod tidy git diff --exit-code go.mod go.sum analyze: name: Analyze results needs: [test, cross_compile, lint] if: always() permissions: # no need to access code contents: none runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe with: jobs: ${{ toJSON(needs) }} docker: name: docker runs-on: ubuntu-latest steps: - name: Check out code uses: actions/checkout@v4 - name: Docker meta id: meta uses: docker/metadata-action@v5 with: # list of Docker images to use as base name for tags images: | restic/restic # generate Docker tags based on the following events/attributes tags: | type=schedule type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} type=sha - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push id: docker_build uses: docker/build-push-action@v5 with: push: false context: . file: docker/Dockerfile pull: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}