Add GraphQL API for upcoming scheduled PEP runs
What does this MR do and why?
Add a new upcomingSchedules field to PipelineExecutionSchedulePolicy GraphQL type that exposes upcoming scheduled runs for pipeline execution schedule policies.
This allows users to see when their scheduled policies will next trigger pipelines across projects, providing visibility into scheduled pipeline execution before building UI.
Changes
- Add
PipelineExecutionProjectScheduleTypeGraphQL type - Add
UpcomingPolicySchedulesResolverwith BatchLoader for N+1 prevention - Add
PipelineExecutionProjectSchedulePolicyfor authorization - Add
preload_policy_and_project_routescope to avoid N+1 queries - Add
upcomingSchedulesfield toPipelineExecutionSchedulePolicyType
The API returns schedule data including next_run_at, cron expression, timezone, time window, and snooze status. Authorization follows existing patterns - users need push_code permission on the policy management project.
Changelog: added EE: true
References
- Related issue: #600939 (closed)
- Parent issue: #558362
Screenshots or screen recordings
Example GraphQL query:
query {
project(fullPath: "root/test-upcoming-schedules") {
pipelineExecutionSchedulePolicies {
nodes {
name
upcomingSchedules(first: 10) {
nodes {
id
project {
fullPath
}
nextRunAt
cron
cronTimezone
timeWindowSeconds
snoozedUntil
}
}
}
}
}
}Example response:
{
"data": {
"project": {
"pipelineExecutionSchedulePolicies": {
"nodes": [
{
"name": "test-schedule-policy",
"upcomingSchedules": {
"nodes": [
{
"id": "gid://gitlab/Security::PipelineExecutionProjectSchedule/27",
"project": {
"fullPath": "root/test-upcoming-schedules"
},
"nextRunAt": "2026-05-29T09:01:56Z",
"cron": "0 8 * * *",
"cronTimezone": "UTC",
"timeWindowSeconds": 14400,
"snoozedUntil": null
}
]
}
}
]
}
}
}
}Database
Query
The resolver generates the following query:
SELECT "security_pipeline_execution_project_schedules".*
FROM "security_pipeline_execution_project_schedules"
WHERE "security_pipeline_execution_project_schedules"."security_policy_id" = 2351295
ORDER BY "security_pipeline_execution_project_schedules"."next_run_at" ASC,
"security_pipeline_execution_project_schedules"."id" ASCQuery plan
Sort (cost=6.35..6.36 rows=3 width=89) (actual time=3.271..3.272 rows=2 loops=1)
Sort Key: security_pipeline_execution_project_schedules.next_run_at, security_pipeline_execution_project_schedules.id
Sort Method: quicksort Memory: 25kB
Buffers: shared hit=9 read=4 dirtied=2
WAL: records=2 fpi=2 bytes=16226
-> Index Scan using idx_pipeline_execution_schedules_security_policy_id_and_id on public.security_pipeline_execution_project_schedules (cost=0.28..6.33 rows=3 width=89) (actual time=2.701..3.226 rows=2 loops=1)
Index Cond: (security_pipeline_execution_project_schedules.security_policy_id = 2351295)
Buffers: shared hit=3 read=4 dirtied=2
WAL: records=2 fpi=2 bytes=16226Existing indexes
The table already has appropriate indexes:
idx_pipeline_execution_schedules_security_policy_id_and_idon(security_policy_id, id)- used by this queryidx_security_pipeline_execution_project_schedules_next_run_aton(next_run_at, id)
No new indexes required.
How to set up and validate locally
-
Create a new group.
-
Create a project in the group to serve as the security policy project.
-
Add a CI config file
policy-ci.yml:test-job: script: - echo "Scheduled policy job running" -
Add a
.gitlab/security-policies/policy.ymlfile (replace<group-path>/<policy-project-path>with the full path to your policy project):--- pipeline_execution_schedule_policy: - name: test-schedule-policy description: 'Test scheduled policy' enabled: true content: include: - project: '<group-path>/<policy-project-path>' file: policy-ci.yml schedules: - type: daily start_time: '10:00' time_window: value: 600 distribution: random -
Enable Pipeline execution policies on the policy project:
- Go to Settings > General > Visibility, project features, permissions
- Enable Pipeline execution policies
- Save changes
-
Go to the group Secure > Policies and link the policy project via Edit policy project.
-
Create another project in the group as the target project.
-
Wait for the policy to sync (this automatically creates the schedule record).
-
Query the GraphQL API at
/-/graphql-explorerusing the example query above (replace the project path with your target project's full path). -
Verify the response includes the schedule with
nextRunAt,cron,cronTimezone, and other fields. -
Verify authorization by querying as a user without
push_codeaccess to the policy project - theupcomingSchedulesshould return empty nodes (the policy itself is visible but schedule details are filtered).
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #600939 (closed)