Skip to content

Resolve "Notifications for when pipelines are fixed"

What does this MR do?

Creates a custom email notification when the pipeline is fixed.

Sends an e-mail for the first green/successful pipeline after a red/failed pipeline on the same commit, branch, or tag.

Technical details

In order to achieve this introduces a ci_ref model which holds the current status of the ref. When a pipeline finishes updates the ci_ref status.

Depending on the ci_ref next status a different notification is sent. When a ci_ref doesn't exists it's created using the pipeline.status as status.

The ci_ref has the following statuses: success, failed, fixed.

The notification triggered are the followings:

event trigger (based on ref next status)
pipeline success [any - failed] > success
pipeline failed any > failed
pipeline fixed failed > success

The pipeline fixed notification is enabled by default and respects the same notification rules as failed pipeline.

The pipeline fixed is a subset of pipeline success thus if the user enabled pipeline success he'll receive the pipeline fixed notification (instead of pipeline success) when the fixed status is hit in the related ci_ref.

Migrations output

== 20191001170300 CreateCiRef: migrating ======================================
-- create_table(:ci_refs, {})
   -> 0.0302s
== 20191001170300 CreateCiRef: migrated (0.0304s) =============================

== 20191111165017 AddFixedPipelineToNotificationSettings: migrating ===========
-- add_column(:notification_settings, :fixed_pipeline, :boolean)
   -> 0.0071s
== 20191111165017 AddFixedPipelineToNotificationSettings: migrated (0.0072s) ==

Complex queries

ruby:

    has_many :pipelines, ->(ref) {
      # We use .read_attribute to save 1 extra unneeded query to load the :project.
      unscope(:where)
        .where(ref: ref.ref, project_id: ref.read_attribute(:project_id), tag: ref.tag)
      # Sadly :inverse_of is not supported (yet) by Rails for composite PKs.
    }, inverse_of: :ci_ref

sql:

SELECT
    "ci_pipelines".*
FROM
    "ci_pipelines"
WHERE
    "ci_pipelines"."ref" = 'master-2'
    AND "ci_pipelines"."project_id" = 19
    AND "ci_pipelines"."tag" = FALSE

on gitlab.com https://explain.depesz.com/s/xhid

ruby:

    has_one :ci_ref, ->(pipeline) {
      # We use .read_attribute to save 1 extra unneeded query to load the :project.
      unscope(:where)
        .where(project_id: pipeline.read_attribute(:project_id), ref: pipeline.ref, tag: pipeline.tag)
      # Sadly :inverse_of is not supported (yet) by Rails for composite PKs.
    }, class_name: 'Ci::Ref', inverse_of: :pipelines

sql:

SELECT
    "ci_refs".*
FROM
    "ci_refs"
WHERE
    "ci_refs"."project_id" = 1
    AND "ci_refs"."ref" = 'master'
    AND "ci_refs"."tag" = FALSE
LIMIT 1

Browser notifications

This MR doesn't handle the fixed browser notification, instead the success notification is shown in both success and fixed cases.

Screenshots

sample html email:

Screenshot_2019-12-31_at_17.30.24

sample plaintext email:

Screenshot_2019-12-31_at_17.31.16

Does this MR meet the acceptance criteria?

Conformity

Performance and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team

Closes #24309 (closed)

Edited by 🙈 jacopo beschi 🙉

Merge request reports