Skip to content

Add user_id indexes to ci_pipelines

Furkan Ayhan requested to merge 217748-user-id-indexes-to-ci-pipelines into master

What does this MR do?

Related to #217748 (closed)

We are implementing filters for pipelines. Right now, we have author and branch name filter. Next, we will implement status and tag name filter. However, before that, we realized that this endpoint has not good ~performance when user filter involves.

This MR aims to improve ~performance of pipeline queries.

Later, we'll cover other points in the issue description.

UP:

== 20200520170433 AddUserIdIndexesToCiPipelines: migrating ====================
-- transaction_open?()
   -> 0.0000s
-- index_exists?(:ci_pipelines, [:project_id, :user_id, :status], {:algorithm=>:concurrently})
   -> 0.0074s
-- add_index(:ci_pipelines, [:project_id, :user_id, :status], {:algorithm=>:concurrently})
   -> 0.0057s
-- transaction_open?()
   -> 0.0000s
-- index_exists?(:ci_pipelines, [:project_id, :user_id, :ref], {:algorithm=>:concurrently})
   -> 0.0049s
-- add_index(:ci_pipelines, [:project_id, :user_id, :ref], {:algorithm=>:concurrently})
   -> 0.0027s
== 20200520170433 AddUserIdIndexesToCiPipelines: migrated (0.0214s) ===========

DOWN:

== 20200520170433 AddUserIdIndexesToCiPipelines: reverting ====================
-- transaction_open?()
   -> 0.0000s
-- index_exists?(:ci_pipelines, [:project_id, :user_id, :status], {:algorithm=>:concurrently})
   -> 0.0126s
-- remove_index(:ci_pipelines, {:algorithm=>:concurrently, :column=>[:project_id, :user_id, :status]})
   -> 0.0114s
-- transaction_open?()
   -> 0.0000s
-- index_exists?(:ci_pipelines, [:project_id, :user_id, :ref], {:algorithm=>:concurrently})
   -> 0.0086s
-- remove_index(:ci_pipelines, {:algorithm=>:concurrently, :column=>[:project_id, :user_id, :ref]})
   -> 0.0101s
== 20200520170433 AddUserIdIndexesToCiPipelines: reverted (0.0437s) ===========

SQL Queries

Endpoint-1: pipelines.json?page=1&scope=all&status=success

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."status" = 'success'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=0.57..46.86 rows=20 width=302) (actual time=11.989..99.235 rows=20 loops=1)
   Buffers: shared read=60 dirtied=23
   I/O Timings: read=85.164
   ->  Index Scan using index_ci_pipelines_on_project_id_and_id_desc on public.ci_pipelines  (cost=0.57..328757.40 rows=142030 width=302) (actual time=11.987..99.224 rows=20 loops=1)
         Index Cond: (ci_pipelines.project_id = 278964)
         Filter: ((ci_pipelines.source <> 12) AND ((ci_pipelines.status)::text = 'success'::text))
         Rows Removed by Filter: 15
         Buffers: shared read=60 dirtied=23
         I/O Timings: read=85.164
Endpoint-2: pipelines.json?page=1&scope=all&status=running

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."status" = 'running'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=417.23..417.28 rows=20 width=302) (actual time=1167.969..1167.980 rows=20 loops=1)
   Buffers: shared hit=57 read=737 dirtied=33
   I/O Timings: read=1148.207
   ->  Sort  (cost=417.23..417.88 rows=259 width=302) (actual time=1167.967..1167.974 rows=20 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: top-N heapsort  Memory: 30kB
         Buffers: shared hit=57 read=737 dirtied=33
         I/O Timings: read=1148.207
         ->  Index Scan using index_ci_pipelines_on_project_id_and_status_and_updated_at on public.ci_pipelines  (cost=0.57..410.34 rows=259 width=302) (actual time=17.478..1166.097 rows=567 loops=1)
               Index Cond: ((ci_pipelines.project_id = 278964) AND ((ci_pipelines.status)::text = 'running'::text))
               Filter: (ci_pipelines.source <> 12)
               Rows Removed by Filter: 1
               Buffers: shared hit=57 read=737 dirtied=33
               I/O Timings: read=1148.207
Endpoint-3: pipelines.json?page=1&scope=all&ref=master

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."ref" = 'master'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=0.57..31.72 rows=20 width=302) (actual time=10.239..11.901 rows=20 loops=1)
   Buffers: shared hit=18 read=6 dirtied=1
   I/O Timings: read=11.716
   ->  Index Scan using index_ci_pipelines_on_project_idandrefandiddesc on public.ci_pipelines  (cost=0.57..139575.91 rows=89605 width=302) (actual time=10.232..11.890 rows=20 loops=1)
         Index Cond: ((ci_pipelines.project_id = 278964) AND ((ci_pipelines.ref)::text = 'master'::text))
         Filter: (ci_pipelines.source <> 12)
         Rows Removed by Filter: 0
         Buffers: shared hit=18 read=6 dirtied=1
         I/O Timings: read=11.716
Endpoint-4: pipelines.json?page=1&scope=all&status=success&ref=master

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."status" = 'success'
  AND "ci_pipelines"."ref" = 'master'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=0.57..31.95 rows=20 width=302) (actual time=12.595..38.989 rows=20 loops=1)
   Buffers: shared read=24 dirtied=8
   I/O Timings: read=35.347
   ->  Index Scan using index_ci_pipelines_on_project_id_and_ref_and_status_and_id on public.ci_pipelines  (cost=0.57..92602.66 rows=59023 width=302) (actual time=12.593..38.973 rows=20 loops=1)
         Index Cond: ((ci_pipelines.project_id = 278964) AND ((ci_pipelines.ref)::text = 'master'::text) AND ((ci_pipelines.status)::text = 'success'::text))
         Filter: (ci_pipelines.source <> 12)
         Rows Removed by Filter: 0
         Buffers: shared read=24 dirtied=8
         I/O Timings: read=35.347
Endpoint-5: pipelines.json?page=1&scope=all&username=furkanayhan

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
INNER JOIN "users" ON "users"."id" = "ci_pipelines"."user_id"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "users"."username" = 'furkanayhan'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

Limit  (cost=1632.88..1632.88 rows=1 width=302) (actual time=762.872..762.880 rows=20 loops=1)
   Buffers: shared hit=4 read=376 dirtied=6
   I/O Timings: read=758.329
   ->  Sort  (cost=1632.88..1632.88 rows=1 width=302) (actual time=762.871..762.878 rows=20 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: top-N heapsort  Memory: 35kB
         Buffers: shared hit=4 read=376 dirtied=6
         I/O Timings: read=758.329
         ->  Nested Loop  (cost=1.00..1632.87 rows=1 width=302) (actual time=71.687..762.087 rows=183 loops=1)
               Buffers: shared hit=1 read=376 dirtied=6
               I/O Timings: read=758.329
               ->  Index Scan using index_users_on_username on public.users  (cost=0.43..4.45 rows=1 width=4) (actual time=10.092..10.094 rows=1 loops=1)
                     Index Cond: ((users.username)::text = 'furkanayhan'::text)
                     Buffers: shared read=4
                     I/O Timings: read=10.047
               ->  Index Scan using index_ci_pipelines_on_user_id_and_created_at on public.ci_pipelines  (cost=0.57..1628.41 rows=1 width=302) (actual time=61.589..751.817 rows=183 loops=1)
                     Index Cond: (ci_pipelines.user_id = users.id)
                     Filter: ((ci_pipelines.source <> 12) AND (ci_pipelines.project_id = 278964))
                     Rows Removed by Filter: 185
                     Buffers: shared hit=1 read=372 dirtied=6
                     I/O Timings: read=748.282
Endpoint-6: pipelines.json?page=1&scope=all&username=furkanayhan&status=success

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
INNER JOIN "users" ON "users"."id" = "ci_pipelines"."user_id"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."status" = 'success'
  AND "users"."username" = 'furkanayhan'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=1635.10..1635.10 rows=1 width=302) (actual time=0.856..0.861 rows=20 loops=1)
   Buffers: shared hit=377
   ->  Sort  (cost=1635.10..1635.10 rows=1 width=302) (actual time=0.855..0.858 rows=20 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: top-N heapsort  Memory: 34kB
         Buffers: shared hit=377
         ->  Nested Loop  (cost=1.00..1635.09 rows=1 width=302) (actual time=0.108..0.756 rows=78 loops=1)
               Buffers: shared hit=377
               ->  Index Scan using index_users_on_username on public.users  (cost=0.43..4.45 rows=1 width=4) (actual time=0.024..0.024 rows=1 loops=1)
                     Index Cond: ((users.username)::text = 'furkanayhan'::text)
                     Buffers: shared hit=4
               ->  Index Scan using index_ci_pipelines_on_user_id_and_created_at on public.ci_pipelines  (cost=0.57..1630.63 rows=1 width=302) (actual time=0.081..0.713 rows=78 loops=1)
                     Index Cond: (ci_pipelines.user_id = users.id)
                     Filter: ((ci_pipelines.source <> 12) AND (ci_pipelines.project_id = 278964) AND ((ci_pipelines.status)::text = 'success'::text))
                     Rows Removed by Filter: 290
                     Buffers: shared hit=373
Endpoint-7: pipelines.json?page=1&scope=all&username=furkanayhan&status=success&ref=master

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
INNER JOIN "users" ON "users"."id" = "ci_pipelines"."user_id"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."status" = 'success'
  AND "ci_pipelines"."ref" = 'master'
  AND "users"."username" = 'furkanayhan'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=1637.32..1637.33 rows=1 width=302) (actual time=633.778..633.778 rows=0 loops=1)
   Buffers: shared hit=4 read=376 dirtied=6
   I/O Timings: read=630.325
   ->  Sort  (cost=1637.32..1637.33 rows=1 width=302) (actual time=633.776..633.776 rows=0 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: quicksort  Memory: 25kB
         Buffers: shared hit=4 read=376 dirtied=6
         I/O Timings: read=630.325
         ->  Nested Loop  (cost=1.00..1637.31 rows=1 width=302) (actual time=633.640..633.640 rows=0 loops=1)
               Buffers: shared hit=1 read=376 dirtied=6
               I/O Timings: read=630.325
               ->  Index Scan using index_users_on_username on public.users  (cost=0.43..4.45 rows=1 width=4) (actual time=8.464..8.467 rows=1 loops=1)
                     Index Cond: ((users.username)::text = 'furkanayhan'::text)
                     Buffers: shared read=4
                     I/O Timings: read=8.421
               ->  Index Scan using index_ci_pipelines_on_user_id_and_created_at on public.ci_pipelines  (cost=0.57..1632.85 rows=1 width=302) (actual time=625.168..625.168 rows=0 loops=1)
                     Index Cond: (ci_pipelines.user_id = users.id)
                     Filter: ((ci_pipelines.source <> 12) AND (ci_pipelines.project_id = 278964) AND ((ci_pipelines.status)::text = 'success'::text) AND ((ci_pipelines.ref)::text = 'master'::text))
                     Rows Removed by Filter: 368
                     Buffers: shared hit=1 read=372 dirtied=6
                     I/O Timings: read=621.904

As it seems, endpoints 5, 6 and 7 have not a good SQL plan.

Right now, `ci_pipelines` table has these indexes:
CREATE INDEX index_ci_pipelines_config_on_pipeline_id ON public.ci_pipelines_config USING btree (pipeline_id);
CREATE INDEX index_ci_pipelines_on_auto_canceled_by_id ON public.ci_pipelines USING btree (auto_canceled_by_id);
CREATE INDEX index_ci_pipelines_on_external_pull_request_id ON public.ci_pipelines USING btree (external_pull_request_id) WHERE (external_pull_request_id IS NOT NULL);
CREATE INDEX index_ci_pipelines_on_merge_request_id ON public.ci_pipelines USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
CREATE INDEX index_ci_pipelines_on_pipeline_schedule_id ON public.ci_pipelines USING btree (pipeline_schedule_id);
CREATE INDEX index_ci_pipelines_on_project_id_and_id_desc ON public.ci_pipelines USING btree (project_id, id DESC);
CREATE UNIQUE INDEX index_ci_pipelines_on_project_id_and_iid ON public.ci_pipelines USING btree (project_id, iid) WHERE (iid IS NOT NULL);
CREATE INDEX index_ci_pipelines_on_project_id_and_ref_and_status_and_id ON public.ci_pipelines USING btree (project_id, ref, status, id);
CREATE INDEX index_ci_pipelines_on_project_id_and_sha ON public.ci_pipelines USING btree (project_id, sha);
CREATE INDEX index_ci_pipelines_on_project_id_and_source ON public.ci_pipelines USING btree (project_id, source);
CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_config_source ON public.ci_pipelines USING btree (project_id, status, config_source);
CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_updated_at ON public.ci_pipelines USING btree (project_id, status, updated_at);
CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_ref ON public.ci_pipelines USING btree (project_id, user_id, ref);
CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_status ON public.ci_pipelines USING btree (project_id, user_id, status);
CREATE INDEX index_ci_pipelines_on_project_idandrefandiddesc ON public.ci_pipelines USING btree (project_id, ref, id DESC);
CREATE INDEX index_ci_pipelines_on_status ON public.ci_pipelines USING btree (status);
CREATE INDEX index_ci_pipelines_on_user_id_and_created_at ON public.ci_pipelines USING btree (user_id, created_at);

After adding these:

CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_ref ON public.ci_pipelines USING btree (project_id, user_id, ref);
CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_status ON public.ci_pipelines USING btree (project_id, user_id, status);

We get these SQL plans for endpoint 5, 6, 7 and 8.

Endpoint-5: pipelines.json?page=1&scope=all&username=stanhu

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
INNER JOIN "users" ON "users"."id" = "ci_pipelines"."user_id"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "users"."username" = 'stanhu'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=7.06..7.07 rows=1 width=302) (actual time=7921.838..7921.844 rows=20 loops=1)
   Buffers: shared hit=11 read=4762
   I/O Timings: read=7839.228
   ->  Sort  (cost=7.06..7.07 rows=1 width=302) (actual time=7921.835..7921.838 rows=20 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: top-N heapsort  Memory: 38kB
         Buffers: shared hit=11 read=4762
         I/O Timings: read=7839.228
         ->  Nested Loop  (cost=1.00..7.05 rows=1 width=302) (actual time=18.487..7907.003 rows=4315 loops=1)
               Buffers: shared hit=11 read=4762
               I/O Timings: read=7839.228
               ->  Index Scan using index_users_on_username on public.users  (cost=0.43..3.45 rows=1 width=4) (actual time=9.020..9.023 rows=1 loops=1)
                     Index Cond: ((users.username)::text = 'stanhu'::text)
                     Buffers: shared read=4
                     I/O Timings: read=8.941
               ->  Index Scan using index_ci_pipelines_on_project_id_and_user_id_and_status on public.ci_pipelines  (cost=0.57..3.59 rows=1 width=302) (actual time=9.457..7890.507 rows=4315 loops=1)
                     Index Cond: ((ci_pipelines.project_id = 278964) AND (ci_pipelines.user_id = users.id))
                     Filter: (ci_pipelines.source <> 12)
                     Rows Removed by Filter: 476
                     Buffers: shared hit=11 read=4758
                     I/O Timings: read=7830.288
Endpoint-6: pipelines.json?page=1&scope=all&username=stanhu&status=success

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
INNER JOIN "users" ON "users"."id" = "ci_pipelines"."user_id"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."status" = 'success'
  AND "users"."username" = 'stanhu'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=7.06..7.07 rows=1 width=302) (actual time=6.705..6.710 rows=20 loops=1)
   Buffers: shared hit=2154
   ->  Sort  (cost=7.06..7.07 rows=1 width=302) (actual time=6.703..6.705 rows=20 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: top-N heapsort  Memory: 38kB
         Buffers: shared hit=2154
         ->  Nested Loop  (cost=1.00..7.05 rows=1 width=302) (actual time=0.057..5.613 rows=2018 loops=1)
               Buffers: shared hit=2154
               ->  Index Scan using index_users_on_username on public.users  (cost=0.43..3.45 rows=1 width=4) (actual time=0.018..0.020 rows=1 loops=1)
                     Index Cond: ((users.username)::text = 'stanhu'::text)
                     Buffers: shared hit=4
               ->  Index Scan using index_ci_pipelines_on_project_id_and_user_id_and_status on public.ci_pipelines  (cost=0.57..3.60 rows=1 width=302) (actual time=0.036..4.712 rows=2018 loops=1)
                     Index Cond: ((ci_pipelines.project_id = 278964) AND (ci_pipelines.user_id = users.id) AND ((ci_pipelines.status)::text = 'success'::text))
                     Filter: (ci_pipelines.source <> 12)
                     Rows Removed by Filter: 124
                     Buffers: shared hit=2150
Endpoint-7: pipelines.json?page=1&scope=all&username=stanhu&status=success&ref=master

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
INNER JOIN "users" ON "users"."id" = "ci_pipelines"."user_id"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."status" = 'success'
  AND "ci_pipelines"."ref" = 'master'
  AND "users"."username" = 'stanhu'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=7.07..7.07 rows=1 width=302) (actual time=4.639..4.645 rows=20 loops=1)
   Buffers: shared hit=2154
   ->  Sort  (cost=7.07..7.07 rows=1 width=302) (actual time=4.638..4.640 rows=20 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: top-N heapsort  Memory: 35kB
         Buffers: shared hit=2154
         ->  Nested Loop  (cost=1.00..7.06 rows=1 width=302) (actual time=0.072..4.174 rows=860 loops=1)
               Buffers: shared hit=2154
               ->  Index Scan using index_users_on_username on public.users  (cost=0.43..3.45 rows=1 width=4) (actual time=0.025..0.026 rows=1 loops=1)
                     Index Cond: ((users.username)::text = 'stanhu'::text)
                     Buffers: shared hit=4
               ->  Index Scan using index_ci_pipelines_on_project_id_and_user_id_and_status on public.ci_pipelines  (cost=0.57..3.60 rows=1 width=302) (actual time=0.044..3.795 rows=860 loops=1)
                     Index Cond: ((ci_pipelines.project_id = 278964) AND (ci_pipelines.user_id = users.id) AND ((ci_pipelines.status)::text = 'success'::text))
                     Filter: ((ci_pipelines.source <> 12) AND ((ci_pipelines.ref)::text = 'master'::text))
                     Rows Removed by Filter: 1282
                     Buffers: shared hit=2150
Endpoint-8: pipelines.json?page=1&scope=all&username=stanhu&ref=master

database-lab

EXPLAIN ANALYZE
SELECT "ci_pipelines".*
FROM "ci_pipelines"
INNER JOIN "users" ON "users"."id" = "ci_pipelines"."user_id"
WHERE "ci_pipelines"."project_id" = 278964
  AND "ci_pipelines"."source" != 12
  AND "ci_pipelines"."ref" = 'master'
  AND "users"."username" = 'stanhu'
ORDER BY "ci_pipelines"."id" DESC LIMIT 20
OFFSET 0;

 Limit  (cost=7.06..7.07 rows=1 width=302) (actual time=10.609..10.615 rows=20 loops=1)
   Buffers: shared hit=4773
   ->  Sort  (cost=7.06..7.07 rows=1 width=302) (actual time=10.607..10.610 rows=20 loops=1)
         Sort Key: ci_pipelines.id DESC
         Sort Method: top-N heapsort  Memory: 35kB
         Buffers: shared hit=4773
         ->  Nested Loop  (cost=1.00..7.05 rows=1 width=302) (actual time=0.069..9.795 rows=1188 loops=1)
               Buffers: shared hit=4773
               ->  Index Scan using index_users_on_username on public.users  (cost=0.43..3.45 rows=1 width=4) (actual time=0.017..0.019 rows=1 loops=1)
                     Index Cond: ((users.username)::text = 'stanhu'::text)
                     Buffers: shared hit=4
               ->  Index Scan using index_ci_pipelines_on_project_id_and_user_id_and_status on public.ci_pipelines  (cost=0.57..3.59 rows=1 width=302) (actual time=0.050..9.161 rows=1188 loops=1)
                     Index Cond: ((ci_pipelines.project_id = 278964) AND (ci_pipelines.user_id = users.id))
                     Filter: ((ci_pipelines.source <> 12) AND ((ci_pipelines.ref)::text = 'master'::text))
                     Rows Removed by Filter: 3603
                     Buffers: shared hit=4769

Besides, all SQL queries have a this condition: "ci_pipelines"."source" != 12, because we have pipelines.no_child condition.

Should we also include this column into indexes? 🤔

Does this MR meet the acceptance criteria?

Conformity

Availability 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
Edited by Furkan Ayhan

Merge request reports