stages: - build - test - analyze - publish - qa default: image: registry.gitlab.com/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:git-2.36 tags: - saas-linux-large-amd64 interruptible: true .versions: debian: "bullseye" git_default: "default" git_minimum: "v2.42.0" gitlab_dangerfiles: "4.5.1" go_default: "1.21" go_supported: [ "1.20", "1.21" ] macos: "macos-12-xcode-14" pgbouncer: "1.17.0" postgres_default: "12-alpine" postgres_minimum: "11-alpine" ruby: "3.2" rust: "1.65" ubi: "8.6" variables: FF_USE_FASTZIP: "true" FF_NETWORK_PER_BUILD: "true" DEBIAN_VERSION: !reference [.versions, debian] UBI_VERSION: !reference [.versions, ubi] CACHE_PREFIX: "debian-${DEBIAN_VERSION}" # We use Gitaly's Git version by default. GIT_VERSION: !reference [.versions, git_default] GO_VERSION: !reference [.versions, go_default] RUBY_VERSION: !reference [.versions, ruby] RUST_VERSION: !reference [.versions, rust] POSTGRES_VERSION: !reference [.versions, postgres_default] PGBOUNCER_VERSION: !reference [.versions, pgbouncer] GOCACHE: "${CI_PROJECT_DIR}/_build/cache/go-build" GOMODCACHE: "${CI_PROJECT_DIR}/_build/cache/go-mod" # We run the build as an untrusted user in a source directory owned by # "root". Running Git commands in that repository will thus fail due to # Git's `safe.directory` protections, and that in turns breaks the Go # build. We work around this by telling Go to not embed VCS information in # the binaries. GOFLAGS: "-buildvcs=false -modcacherw" # Run tests with an intercepted home directory so that we detect cases where # Gitaly picks up the gitconfig even though it ought not to. GITALY_TESTING_INTERCEPT_HOME: "YesPlease" # TEST_UID is the user ID we use to run tests in an unprivileged way. 9999 is # chosen as a semi-random value so as to not interfer with any preexisting # users. TEST_UID: 9999 RAILS_BRANCH_FOR_JOB: "gitaly-ci-jobs-$CI_PIPELINE_IID" include: - template: Security/License-Scanning.gitlab-ci.yml - template: Security/SAST.gitlab-ci.yml - template: Security/Dependency-Scanning.gitlab-ci.yml - template: Security/Secret-Detection.gitlab-ci.yml - project: 'gitlab-org/quality/pipeline-common' file: - '/ci/danger-review.yml' workflow: rules: - if: $CI_MERGE_REQUEST_IID - if: $CI_COMMIT_TAG - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: '$CI_COMMIT_BRANCH =~ /^[\d-]+-stable$/' - if: $FORCE_GITALY_CI .cache_deps: cache: &cache_deps_configuration key: files: - .gitlab-ci.yml - Makefile prefix: ${CACHE_PREFIX}-git-${GIT_VERSION} paths: - _build/deps - _build/tools policy: pull .cache_go: cache: &cache_go_configuration key: files: - .gitlab-ci.yml - go.sum prefix: ${CACHE_PREFIX}-go-${GO_VERSION} paths: - ${GOCACHE} - ${GOMODCACHE} policy: pull .test_template: &test_definition needs: [] stage: test cache: - *cache_deps_configuration - *cache_go_configuration services: - name: postgres:${POSTGRES_VERSION} alias: postgres command: ["postgres", "-c", "max_connections=500"] variables: &test_variables PGHOST: postgres PGPORT: 5432 PGUSER: postgres POSTGRES_DB: praefect_test POSTGRES_HOST_AUTH_METHOD: trust TEST_JUNIT_REPORT: "${CI_PROJECT_DIR}/_build/reports/tests-junit.xml" TEST_COVERAGE_DIR: "${CI_PROJECT_DIR}/_build/reports/coverage" TEST_JSON_REPORT: "${CI_PROJECT_DIR}/_build/reports/test-report.json" TEST_LOG_DIR: "${CI_PROJECT_DIR}/_build/reports/test-logs" TEST_OPTIONS: "-count=1 -timeout=20m" # a number of tests may exceed the default 10m TEST_TMP_DIR: "/tmp" TEST_WITH_COVERAGE: YesPlease before_script: &test_before_script # Speed up test execution by writing test data into tmpfs instead of onto # the underlying disk. - chmod 1777 "${TEST_TMP_DIR}" - mount none -t tmpfs -o size=4G "${TEST_TMP_DIR}" - go version script: # Create the build directory for the unprivileged user that we're running # tests as. This is required because the source directory itself is owned # by `root`. - install --directory --owner=${TEST_UID} --group=${TEST_UID} _build # But the actual tests should run unprivileged. This assures that we pay # proper attention to permission bits and that we don't modify the source # directory. - setpriv --reuid=${TEST_UID} --regid=${TEST_UID} --clear-groups --no-new-privs make ${TEST_TARGET} $(test "${GIT_VERSION}" = default && echo WITH_BUNDLED_GIT=YesPlease) coverage: /^total:\t+\(statements\)\t+\d+\.\d+%$/ after_script: &test_after_script - go run "${CI_PROJECT_DIR}/tools/panic-parser" - | echo -e "section_start:$(date +%s):coverage[collapsed=true]\r\e[0KCode Coverage" go tool cover -func "${TEST_COVERAGE_DIR}/all.merged" echo -e "section_end:$(date +%s):coverage\r\e[0K" artifacts: &test_artifacts paths: - ${TEST_LOG_DIR} reports: junit: ${TEST_JUNIT_REPORT} coverage_report: coverage_format: cobertura path: ${TEST_COVERAGE_DIR}/cobertura.xml when: always expire_in: 1 week .rules_run_on_merge: &rules_run_on_merge # We only execute these rules in the main Gitaly repository. This is # because jobs which run conditionally when being merged may depend on # specific runners that aren't available in any other repository. - if: $CI_PROJECT_PATH != "gitlab-org/gitaly" when: manual allow_failure: true # Automatically run the job when the default branch is changing, e.g. due # to a direct push. - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Automatically run the job when a merge request gets queued for merge. - if: $CI_MERGE_REQUEST_EVENT_TYPE == "merge_train" # Otherwise, allow for manually scheduling the job in the context of a # merge request. - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: manual allow_failure: true # Manual pipeline run outside of merge requests, such as when setting # custom CI variables via the Pipelines page. - if: $FORCE_GITALY_CI danger-review: needs: [] stage: build allow_failure: true variables: GITLAB_DANGERFILES_VERSION: !reference [.versions, gitlab_dangerfiles] build: needs: [] stage: build cache: - <<: *cache_deps_configuration policy: pull-push - <<: *cache_go_configuration policy: pull-push script: - go version # Build the binaries as unprivileged user so that we can reuse the cache # for our "test" targets, which also run unprivileged. - install --directory --owner=${TEST_UID} --group=${TEST_UID} _build - setpriv --reuid=${TEST_UID} --regid=${TEST_UID} --clear-groups --no-new-privs make build $(test "${GIT_VERSION}" = default && echo build-bundled-git || echo build-git) - go run ./tools/test-boot ${TEST_BOOT_ARGS} parallel: matrix: - GO_VERSION: !reference [.versions, go_supported] TEST_BOOT_ARGS: "--bundled-git" - GIT_VERSION: !reference [.versions, git_minimum ] build:binaries: needs: [] stage: build cache: - *cache_deps_configuration - *cache_go_configuration script: # Just in case we start running CI builds on other architectures in future - go version - make -j$(nproc) build - cd _build && sha256sum bin/* | tee checksums.sha256.txt artifacts: paths: - _build/checksums.sha256.txt - _build/bin/ name: "${CI_JOB_NAME}:go-${GO_VERSION}-git-${GIT_VERSION}" expire_in: 6 months parallel: matrix: - GO_VERSION: !reference [.versions, go_supported] rules: - if: $CI_COMMIT_TAG test: <<: *test_definition parallel: matrix: # The following jobs all test with our default Git version, which is # using bundled Git binaries. - GO_VERSION: !reference [.versions, go_supported] TEST_TARGET: test - TEST_TARGET: [ test-with-praefect, race-go, test-wal, test-with-praefect-wal] # We also verify that things work as expected with a non-bundled Git # version matching our minimum required Git version. - TEST_TARGET: test GIT_VERSION: !reference [.versions, git_minimum] # Execute tests with our minimum required Postgres version, as well. If # the minimum version changes, please change this to the new minimum # version. Furthermore, please make sure to update the minimum required # version in `datastore.CheckPostgresVersion()`. - POSTGRES_VERSION: !reference [.versions, postgres_minimum] TEST_TARGET: [ test, test-with-praefect ] test:pgbouncer: <<: *test_definition services: - name: postgres:${POSTGRES_VERSION} alias: postgres command: ["postgres", "-c", "max_connections=500"] - name: bitnami/pgbouncer:${PGBOUNCER_VERSION} alias: pgbouncer variables: <<: *test_variables # The following variables are used by PgBouncer to connect to Postgres. POSTGRESQL_HOST: "${PGHOST}" POSTGRESQL_PORT: "${PGPORT}" POSTGRESQL_USERNAME: "${PGUSER}" # These variables define how PgBouncer itself is configured PGBOUNCER_AUTH_TYPE: trust PGBOUNCER_AUTH_USER: "${PGUSER}" PGBOUNCER_DATABASE: "*" PGBOUNCER_IGNORE_STARTUP_PARAMETERS: extra_float_digits PGBOUNCER_POOL_MODE: transaction PGBOUNCER_MAX_CLIENT_CONN: 500 PGBOUNCER_MAX_DB_CONNECTIONS: 100 # And these are finally used by Gitaly's tests. PGHOST_PGBOUNCER: pgbouncer PGPORT_PGBOUNCER: 6432 # We need to enable per-build networking such that the PgBouncer service # can reach Postgres. TEST_TARGET: "test-with-praefect" test:nightly: <<: *test_definition variables: <<: *test_variables SKIP_OVERRIDING_GIT_VERSION: "YesPlease" parallel: matrix: - GIT_VERSION: [ "master", "next" ] TEST_TARGET: [ test, test-with-praefect ] rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' - when: manual allow_failure: true test:praefect_smoke: <<: *test_definition script: - make -j$(nproc) - envsubst < _support/config.praefect.toml.ci-sql-test > config.praefect.toml - ./_build/bin/praefect -config config.praefect.toml sql-ping - ./_build/bin/praefect -config config.praefect.toml sql-migrate test:sha256: <<: *test_definition parallel: matrix: - TEST_TARGET: [ test, test-with-praefect, test-wal, test-with-praefect-wal ] TEST_WITH_SHA256: "YesPlease" test:fips: <<: *test_definition image: registry.gitlab.com/gitlab-org/gitlab-build-images/ubi-${UBI_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:git-2.36 tags: - fips cache: - <<: *cache_deps_configuration policy: pull-push - <<: *cache_go_configuration policy: pull-push variables: <<: *test_variables CACHE_PREFIX: ubi-${UBI_VERSION} before_script: - *test_before_script - dnf install -y python3 - test "$(cat /proc/sys/crypto/fips_enabled)" = "1" || (echo "System is not running in FIPS mode" && exit 1) parallel: matrix: - TEST_TARGET: [ test, test-with-praefect ] FIPS_MODE: "YesPlease" GO_VERSION: !reference [.versions, go_supported] rules: # Automatically run the job when the FIPS label is set. - if: $CI_MERGE_REQUEST_LABELS =~ /FIPS/ - *rules_run_on_merge test:macos: image: !reference [.versions, macos] tags: - saas-macos-medium-m1 needs: [] stage: test cache: - <<: *cache_deps_configuration policy: pull-push - <<: *cache_go_configuration policy: pull-push variables: <<: *test_variables CACHE_PREFIX: !reference [.versions, macos] PGDATA: /Volumes/RAMDisk/postgres PGHOST: localhost PGUSER: gitlab TEST_TMP_DIR: /Volumes/RAMDisk # Disable code coverage generation as it is too slow on macOS. TEST_WITH_COVERAGE: "" before_script: # Disable Gatekeeper to speed up spawning executables. - sudo spctl --master-disable # Create a 2GB RAM disk to speed up our tests. - sudo diskutil apfs create $(hdiutil attach -nomount ram://4194304) RAMDisk - brew uninstall go - brew install cmake go@${GO_VERSION} # Older Go versions may be keg-only and thus aren't linked into `PATH` by # default. We need to override this mechanism to force this specific Go # version to become active. - brew link --force go@${GO_VERSION} - sw_vers - go version - pg_ctl --version - ulimit -n 4096 # The default of 256 can lead to 'too many open files' errors when running parallel tests - pg_ctl init - pg_ctl start - pg_ctl status - createdb -U $PGUSER $POSTGRES_DB - make -j$(nproc) build prepare-tests script: - make test-go ; EXIT_CODE=$? ; pg_ctl stop ; exit $EXIT_CODE after_script: - *test_after_script rules: - *rules_run_on_merge artifacts: <<: *test_artifacts verify:docs: image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.18-vale-2.27.0-markdownlint-0.35.0-markdownlint2-0.8.1 needs: [] stage: analyze script: - make lint-docs verify: needs: [] stage: analyze cache: - *cache_deps_configuration - *cache_go_configuration script: # Download the dependencies in case there was no cache hit, otherwise # golang-ci lint will timeout downloading them. - go mod download - make -j$(nproc) verify artifacts: paths: - _build/proto.diff - proto/go/gitalypb/* when: on_failure dbschema: needs: [] stage: analyze cache: - *cache_deps_configuration - *cache_go_configuration services: # The database version we use must match the version of `pg_dump` we have # available in the build image. - postgres:11.13-alpine variables: <<: *test_variables script: - make dump-database-schema no-changes artifacts: paths: - _support/praefect-schema.sql when: on_failure semgrep-sast: needs: [] stage: analyze cache: - *cache_go_configuration rules: - if: $SAST_DISABLED when: never license_scanning: needs: [] stage: analyze rules: - if: $LICENSE_SCANNING_DISABLED when: never variables: LICENSE_FINDER_CLI_OPTS: '--aggregate-paths=.' secret_detection: needs: [] stage: analyze rules: - if: $SECRET_DETECTION_DISABLED when: never build-proto-gem: needs: [] image: ruby:${RUBY_VERSION} stage: publish before_script: [] variables: BUILD_GEM_OPTIONS: --skip-verify-tag script: - make build-proto-gem rules: - when: manual allow_failure: true artifacts: paths: - _build/gitaly.gem expire_in: 1 month publish-proto-gem: needs: [] image: ruby:${RUBY_VERSION} stage: publish before_script: [] script: - make publish-proto-gem rules: - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_COMMIT_TAG' pages: needs: [] stage: publish allow_failure: true script: - make build-proto-docs - mv _build/proto-docs public artifacts: paths: - public rules: - *rules_run_on_merge start-rails-specs: needs: [] stage: qa script: - | curl --fail --request POST --header "PRIVATE-TOKEN: $GITLAB_PROJECT_TOKEN" \ "https://gitlab.com/api/v4/projects/278964/repository/branches?ref=master&branch=$RAILS_BRANCH_FOR_JOB" - | curl --fail --request PUT --header "PRIVATE-TOKEN: $GITLAB_PROJECT_TOKEN" \ --data "branch=$RAILS_BRANCH_FOR_JOB" \ --data "content=$CI_COMMIT_SHA" \ --data "commit_message=Updating GITALY_SERVER_VERSION to $CI_COMMIT_SHA" \ "https://gitlab.com/api/v4/projects/278964/repository/files/GITALY_SERVER_VERSION" environment: name: merge-requests/$RAILS_BRANCH_FOR_JOB on_stop: rails-specs-cleanup rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_EVENT_TYPE != "merge_train" when: manual allow_failure: true rails-specs: needs: ["start-rails-specs"] stage: qa trigger: project: gitlab-org/gitlab branch: "gitaly-ci-jobs-$CI_PIPELINE_IID" # Using $RAILS_BRANCH_FOR_JOB directly fails strategy: depend inherit: variables: false # Otherwise variables will be messed up variables: GITALY_TEST: "true" ENABLE_RSPEC: "true" ENABLE_RSPEC_UNIT: "true" ENABLE_RSPEC_INTEGRATION: "true" ENABLE_RSPEC_SYSTEM: "true" rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_EVENT_TYPE != "merge_train" rails-specs-cleanup: stage: qa needs: ["rails-specs"] script: - | curl --fail --request DELETE --header "PRIVATE-TOKEN: $GITLAB_PROJECT_TOKEN" \ "https://gitlab.com/api/v4/projects/278964/repository/branches/$RAILS_BRANCH_FOR_JOB" environment: name: merge-requests/$RAILS_BRANCH_FOR_JOB action: stop rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_EVENT_TYPE != "merge_train" when: manual cleanup-rails-spec-test-env: needs: ["rails-specs-cleanup"] stage: qa before_script: - apt update - apt install -y jq script: - | ENV_ID=$(curl -s --request GET --header "PRIVATE-TOKEN: $GITALY_PROJECT_TOKEN" "https://gitlab.com/api/v4/projects/2009901/environments" --data-urlencode "name=merge-requests/$RAILS_BRANCH_FOR_JOB" | jq '.[0].id') curl --fail -s --request DELETE --header "PRIVATE-TOKEN: $GITALY_PROJECT_TOKEN" "https://gitlab.com/api/v4/projects/2009901/environments/$ENV_ID" rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_EVENT_TYPE != "merge_train" build-package-and-qa: needs: [] stage: qa trigger: project: gitlab-org/build/omnibus-gitlab-mirror strategy: depend variables: ALTERNATIVE_SOURCES: "true" GITALY_SERVER_VERSION: $CI_COMMIT_SHA GITALY_SERVER_ALTERNATIVE_REPO: $CI_PROJECT_URL ee: "true" rules: - if: $CI_MERGE_REQUEST_IID changes: - go.sum variables: BUILD_ON_ALL_OS: "true" MANUAL_QA_TEST: "true" allow_failure: false - when: manual allow_failure: true qa:nightly-praefect-migration-test: needs: [] stage: qa trigger: project: gitlab-org/quality/praefect-migration-testing rules: - if: '$CI_PIPELINE_SOURCE == "schedule"'