Open-Source Wikis

/

GitLab

/

How to contribute

/

Development workflow

gitlab-org/gitlab

Development workflow

The mechanics of writing, testing, and shipping a change to GitLab.

Branching

The default branch is master. Branch names should:

  • Be lowercased with hyphens.
  • Include the issue number when applicable: 123456-fix-pipeline-cache.
  • Avoid wip/ prefixes — use the MR's "Mark as draft" toggle instead.

The .ai/git.md file (loaded by AI assistants) lists the project's git conventions.

Commit hygiene

  • Each commit should be self-contained, build, and pass lint locally.
  • Subject line ≤ 72 characters.
  • Squashing on merge is the default; commits within an MR may be exploratory.

Pre-commit checks via Lefthook

The repo uses Lefthook for git hooks (lefthook.yml, ~17K lines of config). After installing GDK or running lefthook install, a pre-push hook runs the relevant linters on the files you changed:

  • RuboCop on *.rb
  • HAML-Lint on *.haml
  • ESLint on *.js / *.vue
  • Stylelint on *.scss
  • Prettier
  • Markdownlint
  • gettext-lint

Hooks can be skipped with LEFTHOOK=0 git push, but this is discouraged.

Local CI scripts

Several helper scripts in scripts/ reproduce CI locally:

  • scripts/run-fast-specs.sh — RSpec subset that runs in seconds.
  • scripts/static-analysis — runs RuboCop, ESLint, Stylelint, etc.
  • scripts/lint-doc.sh — full doc lint suite.
  • scripts/regenerate-schema — re-dump db/structure.sql after a migration.
  • scripts/verify-tff-mapping — validates the test-file-finder mapping for selective test execution.

Working with feature flags

New code that's not 100% ready for production is gated behind a feature flag. The flow is:

  1. Create the flag YAML: config/feature_flags/development/<flag_name>.yml (or gitlab_com_derisk/, beta/, experiment/, wip/, ops/ depending on lifecycle).
  2. Wrap code with Feature.enabled?(:flag_name, actor) from lib/feature.rb.
  3. Spec the flag both on and off.
  4. Roll out by chatops, then promote to GA with a clean-up MR removing the flag.

See Feature flags.

Adding a database migration

Use the generator:

bin/rails generate migration AddFooToBars foo:string

Migrations are constrained:

  • Forward migrations live in db/migrate/.
  • Post-deploy migrations (data backfills, index drops) live in db/post_migrate/.
  • Long-running data work uses Gitlab::BackgroundMigration (lib/gitlab/background_migration/).
  • Time-based partitions use lib/gitlab/database/partitioning/.
  • Strict rules in lib/gitlab/database/migration_helpers.rb and the migration_style_guide doc.

After writing the migration, regenerate the structure:

bin/rake db:migrate
scripts/regenerate-schema

Schema validators in scripts/validate_* and scripts/migration_schema_validator.rb will block CI if you forget.

Adding a controller / endpoint

For a UI page:

  1. Add a route in config/routes/<area>.rb.
  2. Create the controller under app/controllers/<area>/.
  3. Add a feature category at the top: feature_category :foo.
  4. Add a Devise/Doorkeeper auth guard.
  5. Defer business logic to a service in app/services/<bounded_context>/<verb>_service.rb.

For a REST endpoint:

  1. Add a Grape file under lib/api/<area>.rb.
  2. Mount it in lib/api/api.rb.
  3. Use present, not_found!, and the helper modules in lib/api/helpers/.

For a GraphQL field:

  1. Add a type under app/graphql/types/.
  2. For mutations, add to app/graphql/mutations/<area>/.
  3. For queries with N+1 concerns, use a BatchLoader.

Adding a worker (Sidekiq job)

  1. Create app/workers/<area>/<verb>_worker.rb.

  2. Include ApplicationWorker and declare:

    class MyWorker
      include ApplicationWorker
      idempotent!
      feature_category :my_category
      urgency :low
      deduplicate :until_executed
    end
  3. Add the queue to config/sidekiq_queues.yml if it's a new namespace.

  4. Run bin/rake gitlab:sidekiq:all_queues_yaml:generate to refresh app/workers/all_queues.yml.

See Sidekiq jobs for the full pattern.

Pushing and opening the MR

When you're ready:

git push -u origin <branch>

The push response includes a "Create merge request" URL. The MR template prompts you for:

  • Description ("What does this MR do and why?").
  • Screenshots / screen recordings for UI changes.
  • Required action checklist.
  • Database review request when migrations or schema changes are present.

After merge

A merged MR triggers:

  • An auto-deployment cycle: code rolls out to staging, then canary, then production (GitLab.com).
  • Inclusion in the next monthly release tag (the 22nd of each month).
  • A changelog entry generated by scripts/release_environment/.

If your change introduces a regression, the release tools provide a backport process; scripts/backport_fix_to_stable_branch automates much of it.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – GitLab wiki | Factory