Repository navigation
137 lines (130 loc) · 7.53 KB
/
Copy pathcodeql.yml
File metadata and controls
137 lines (130 loc) · 7.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
name: 'CodeQL'
# CodeQL moved from GitHub's DEFAULT SETUP to advanced setup for exactly one reason:
# default setup cannot be given a concurrency policy.
#
# Default setup has no workflow file — GitHub generates the run server-side, which is why its
# runs show up under the path `dynamic/github-code-scanning/codeql` instead of this directory.
# There is nowhere to put a `concurrency:` block, and GitHub does not supersede its own runs, so
# every push to a pull request started ANOTHER full analysis alongside the ones already running.
# Measured on #10254 on 2026-09-21: runs 35547460875 (00:21→00:52) and 35548451790 (00:40→01:14)
# overlapped by 12 minutes, and 35580875040 / 35582701347 / 35582925033 were all in flight at
# 09:22. Each run is two jobs of roughly 25-35 minutes on the 4-vCPU ARC pool, so every overlap
# pinned two extra self-hosted runner pods to a commit that had already been superseded.
#
# This file reproduces what default setup was configured to do — same languages, the default
# query suite, the default (remote) threat model, the same weekly schedule and the same runner
# label — and adds the one thing it could not have.
#
# Parity note: default setup listed four languages (actions, javascript, javascript-typescript,
# typescript), but `javascript`, `typescript` and `javascript-typescript` are three names for one
# analysis — its runs only ever produced two jobs, and the uploaded analyses only ever carried the
# categories `/language:javascript-typescript` and `/language:actions`. The matrix below is those
# two, which is the same coverage and not a reduction.
# Branch list is parity, not a widening. Default setup scans the default branch AND every
# protected branch, plus pull requests targeting them — and `develop`, `stage` and `master` are
# all protected on this repository, so default setup was already scanning all three. Confirmed
# against the uploaded analyses, which include `refs/heads/stage` as well as `refs/heads/develop`.
# Listing only `develop` here would have quietly dropped CodeQL from the release cascade.
on:
push:
branches:
- develop
- stage
- master
pull_request:
# Off by owner decision (2026-09-21): a pull request INTO develop does not start this workflow. The
# cost belonged to every commit on the branch being merged, and the run belongs to the merge — the
# `push` trigger above still scans develop, stage and master when code lands on them, so nothing goes
# unscanned. Pull requests aimed at `stage` and `master` still run it, which is the release cascade.
#
# Measured on 2026-09-22 before this change, over the previous twelve runs: 178 run-minutes in total,
# 137 of them on pull requests, at two jobs of 22-45 minutes each on the 4-vCPU ARC pool — paid on
# every contributor's branch into develop, not just one (`feat/platform-extensions`, `develop`,
# `fix/custom-dashboard-drag-and-drop`, `feat/9873-restrict-agent-exit-logout`).
#
# `branches-ignore` rather than a `branches` list, because a list is what has to be edited when a new
# protected branch appears and this is the exception to it. `build.yml` and `secrets-analysis.yml`
# already spell their develop exception this way.
#
# To restore the pull-request trigger, replace this block with:
# branches:
# - develop
# - stage
# - master
branches-ignore:
- develop
# Default setup ran a weekly scan so that a new CodeQL release re-examines unchanged code.
# Keeping it means an advisory published after a file was last touched still finds it.
schedule:
- cron: '27 4 * * 1'
workflow_dispatch:
concurrency:
# The point of this file. A newer commit on the same ref wins and the superseded analysis is
# killed. Safe here in a way it is not for the deploy and release workflows: this job only reads
# the checkout and uploads a SARIF result, so a half-finished run leaves nothing behind — the
# next run re-uploads the complete picture for that ref. Nothing downstream is wired to this
# workflow's conclusion (no `workflow_run` consumer), and none of develop/stage/master declares
# a required status check, so a cancelled run cannot wedge a pull request's merge gate either.
# If required checks are ever introduced, re-check this line before trusting it.
#
# Keyed on the HEAD REF rather than `github.ref`, for the same reason and with the same trade-off
# as `build.yml`: both triggers above cover develop/stage/master, so while a cascade pull request
# is open (develop -> stage), one push to `develop` fires a push run on `refs/heads/develop` AND a
# pull_request run on `refs/pull/N/merge`. Under `github.ref` those are different strings, so
# neither could cancel the other and the same tree was analyzed twice. Qualified by the head
# REPOSITORY as well, because a fork pull request's run claims the group before its job skips.
group: >-
${{ github.workflow }}-${{ github.event_name == 'pull_request'
&& format('{0}@{1}', github.event.pull_request.head.repo.full_name, github.event.pull_request.head.ref)
|| format('{0}@{1}', github.repository, github.ref_name) }}
cancel-in-progress: true
# Least privilege at the workflow level; the analyze job widens only what CodeQL needs.
permissions:
contents: read
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Never run jobs for a pull request from a fork (owner decision 2026-09-16); branch PRs and pushes still run.
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
# Same pool default setup used (`runner_label: ever-k8s-linux-x64-4`), read through the repo
# variable the rest of this directory uses so a fleet rename is a one-place change. The
# fallback keeps the workflow runnable if the ARC pool is ever unavailable.
runs-on: ${{ vars.RUNNER_LINUX_X64_4 || 'ubuntu-24.04' }}
timeout-minutes: 120
permissions:
# Upload the SARIF results to the code scanning API. Required by every advanced setup.
security-events: write
# Lets the `actions` language analysis read workflow definitions and run metadata.
actions: read
# Fetching CodeQL query packs.
packages: read
contents: read
strategy:
# One language failing must not hide the other language's findings.
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
- language: actions
build-mode: none
steps:
- uses: actions/checkout@v5
with:
# Analysis only reads the tree; the checkout credential does not need to outlive the step.
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# No `queries:` and no `config:` on purpose. Default setup ran `query_suite: default`
# with `threat_model: remote`, and both of those ARE the action's defaults — naming them
# explicitly would not change the analysis, it would only create a second place to keep
# in sync. Widen to `security-extended` here if the team ever decides to.
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
# Produces the same `/language:<lang>` category default setup uploaded, so the existing
# alerts are matched rather than duplicated as a new tool's findings.
category: '/language:${{ matrix.language }}'