Skip to content

About scm-engine

What is scm-engine?

SCM Engine allow for easy Merge Request automation within your GitLab projects.

Automatically add/remove labels depending on files changes, the age of the Merge Request, who contributes, and pretty much anything else you could want.

You can even take actions such as (but not limited to) closing the Merge Request, approve it, or add a comment.

SCM engine can be run either as a regular CI job in your pipeline, or be triggered through the Webhook system, allowing for versatile and flexible deployments.

What does it look like?

Please see the Configuration Examples page for more use-cases

Please see the Configuration Options page for all options and explanations

# yaml-language-server: $schema=https://jippi.github.io/scm-engine/scm-engine.schema.json  # Expr-Lang # # Language Definition: https://expr-lang.org/docs/language-definition # # SCM-engine # # Config file: https://jippi.github.io/scm-engine/configuration/ # Variables : https://jippi.github.io/scm-engine/gitlab/script-attributes/ # Functions : https://jippi.github.io/scm-engine/gitlab/script-functions # GitHub : https://github.com/jippi/scm-engine/  actions:  - name: Warn about closing the MR if there have been no commit activity for 3 weeks  group: close_mr_lifecycle  if: |1  merge_request.state_is("opened")  && merge_request.has_no_label("do-not-close")  && merge_request.has_no_label("security")  && merge_request.author.username != "renovate-bot"  && merge_request.time_since_last_commit > duration("3w")  && none(merge_request.notes, .body contains "scm-engine-mr-lifecycle:warn")  then:  - action: comment  message: |  <!-- scm-engine-mr-lifecycle:warn -->  :wave: Hello!   This Merge Request has not seen any commit activity for 3 weeks.  We will automatically close the Merge request in 1 week to keep our project clean.   To disable this behavior, add the `do-not-close` label to the Merge Request in the right menu or add a comment with `/label ~"do-not-close"`.   - name: Close the MR if there have been no commit activity for 4 weeks  group: close_mr_lifecycle  if: |1  merge_request.state_is("opened")  && merge_request.has_no_label("do-not-close")  && merge_request.has_no_label("security")  && merge_request.author.username != "renovate-bot"  && merge_request.time_since_last_commit > duration("4w")  && none(merge_request.notes, .body contains "scm-engine-mr-lifecycle:close")  && any(merge_request.notes, .body contains "scm-engine-mr-lifecycle:warn" && since(.created_at) > duration("1w"))  then:  - action: close  - action: comment  message: |  <!-- scm-engine-mr-lifecycle:close -->  :wave: Hello!   This Merge Request has not seen any commit activity for 4 weeks.  To keep our project clean, we will close the Merge request now.   To disable this behavior, add the `do-not-close` label to the Merge Request in the right menu or add a comment with `/label ~"do-not-close"`.   - name: Approve MR if the 'break-glass-approve' label is configured  if: |1  merge_request.state_is("opened")  && not merge_request.approved  && merge_request.has_label("break-glass-approve")  then:  - action: approve   - action: comment  message: "Approving the MR since it has the 'break-glass-approve' label. Talk to ITGC about this!"   - name: Assign Reviewers to MR (only when MR is unassigned)  group: assign_mr  if: |1  merge_request.state_is("opened")  && not merge_request.approved  then:  - action: assign_reviewers  source: codeowners  limit: 1  label:  - name: lang/go  color: $indigo  script: merge_request.modified_files("*.go")   - name: lang/markdown  color: $indigo  description: Modified MarkDown files  script: merge_request.modified_files("*.md")   - name: dependencies/go  color: $orange  description: Updated Go dependency files go.mod or go.sum  script: merge_request.modified_files("go.mod", "go.sum")   - name: type/ci  color: $green  description: Modified CI files  script: merge_request.modified_files(".gitlab-ci.yml") || merge_request.modified_files("build/")   - name: type/deployment  color: $green  description: Modified Deployment files  script: merge_request.modified_files("_infrastructure/", "scripts/", "configs/")   - name: type/documentation  color: $green  description: Modified Documentation files  script: merge_request.modified_files("docs/")   - name: type/services  color: $green  description: Modified pkg/services files  script: merge_request.modified_files("internal/pkg/services")   # NOTE: This label assume your GitLab supports scoped labels  # See: https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels  - name: go::tests::missing  color: $red  description: The Merge Request did NOT modify Go test files  priority: 999  script: not merge_request.modified_files("*_test.go") && merge_request.modified_files("*.go")   # NOTE: This label assume your GitLab supports scoped labels  # See: https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels  - name: go::tests::OK  color: $green  description: The Merge Request modified Go test files  priority: 999  script: merge_request.modified_files("*_test.go") && merge_request.modified_files("*.go")   # NOTE: This label assume your GitLab supports scoped labels  # See: https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels  - name: status::age::abandoned  color: $red  description: The most recent commit is older than 45 days  priority: 999  script: merge_request.time_since_last_commit > duration("45d")  skip_if: merge_request.state in ["merged", "closed", "locked"]   # NOTE: This label assume your GitLab supports scoped labels  # See: https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels  - name: status::age::stale  color: $red  description: The most recent commit is older than 30 days  priority: 999  script: duration("30d") < merge_request.time_since_last_commit < duration("45d")  skip_if: merge_request.state in ["merged", "closed", "locked"]   # NOTE: This label assume your GitLab supports scoped labels  # See: https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels  - name: status::age::old  color: $red  description: The most recent commit is older than 14 days  priority: 999  script: duration("14d") < merge_request.time_since_last_commit < duration("30d")  skip_if: merge_request.state in ["merged", "closed", "locked"]   # generate labels for services  #  # internal/service/vault/client.go  # =>  # service/vault  - strategy: generate  description: Modified this a service directory  color: $pink  script: >  merge_request.modified_files_list("internal/service/")  | map({ filepath_dir(#) })  | map({ trimPrefix(#, "internal/") })  | uniq()   # generate labels for commands  #  # internal/app/my-command/subcommands/aws/login/login.go  # =>  # command/aws/login  - strategy: generate  description: Modified this my-command command  color: $purple  script: >  merge_request.modified_files_list("internal/app/my-command/subcommands/")  | map({ filepath_dir(#) })  | map({ trimPrefix(#, "internal/app/my-command/subcommands/") })  | map({ string("command/" + #) })  | uniq()