Skip to content

Commit 1712e17

Browse files
committed
Added monthly IWYU cleanup workflow.
1 parent 09f8077 commit 1712e17

2 files changed

Lines changed: 252 additions & 5 deletions

File tree

.github/workflows/iwyu.yml

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
name: IWYU.
2+
3+
on:
4+
schedule:
5+
- cron: '0 3 1 * *'
6+
workflow_dispatch:
7+
inputs:
8+
ref:
9+
description: 'Branch to clean up.'
10+
type: string
11+
default: dev
12+
push:
13+
branches: [iwyu-test]
14+
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
19+
jobs:
20+
21+
generate:
22+
name: Generate patch
23+
runs-on: depot-ubuntu-latest-16
24+
outputs:
25+
has_changes: ${{ steps.diff.outputs.has_changes }}
26+
ref: ${{ steps.target.outputs.ref }}
27+
env:
28+
IMAGE_TAG: tdesktop:centos_env
29+
30+
steps:
31+
- name: Resolve target ref.
32+
id: target
33+
run: echo "ref=${{ inputs.ref || (github.event_name == 'push' && github.ref_name) || 'dev' }}" >> $GITHUB_OUTPUT
34+
35+
- name: Clone.
36+
uses: actions/checkout@v6
37+
with:
38+
ref: ${{ steps.target.outputs.ref }}
39+
submodules: recursive
40+
41+
- name: First set up.
42+
run: |
43+
sudo apt update
44+
curl -sSL https://install.python-poetry.org | python3 -
45+
cd Telegram/build/docker/centos_env
46+
poetry install
47+
DOCKERFILE=$(DEBUG= LTO= poetry run gen_dockerfile)
48+
echo "$DOCKERFILE" > Dockerfile
49+
rm -rf __pycache__
50+
51+
- name: Free up some disk space.
52+
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
53+
with:
54+
tool-cache: true
55+
56+
- name: Set up Docker Buildx.
57+
uses: docker/setup-buildx-action@v4
58+
59+
- name: Libraries cache.
60+
uses: actions/cache@v5
61+
with:
62+
path: ${{ runner.temp }}/.buildx-cache
63+
key: ${{ runner.OS }}-libs-${{ hashFiles('Telegram/build/docker/centos_env/**') }}
64+
restore-keys: ${{ runner.OS }}-libs-
65+
66+
- name: Libraries.
67+
uses: docker/build-push-action@v7
68+
with:
69+
context: Telegram/build/docker/centos_env
70+
load: true
71+
tags: ${{ env.IMAGE_TAG }}
72+
cache-from: type=local,src=${{ runner.temp }}/.buildx-cache
73+
cache-to: type=local,dest=${{ runner.temp }}/.buildx-cache-new,mode=max
74+
75+
- name: Move cache.
76+
run: |
77+
rm -rf ${{ runner.temp }}/.buildx-cache
78+
mv ${{ runner.temp }}/.buildx-cache{-new,}
79+
80+
- name: Configure & build (codegen + compile_commands).
81+
run: |
82+
docker run --rm \
83+
-u $(id -u) \
84+
-v $PWD:/usr/src/tdesktop \
85+
-e CONFIG=Debug \
86+
$IMAGE_TAG \
87+
/usr/src/tdesktop/Telegram/build/docker/centos_env/build.sh \
88+
-D CMAKE_CONFIGURATION_TYPES=Debug \
89+
-D CMAKE_C_FLAGS_DEBUG="-O0 -fuse-ld=lld" \
90+
-D CMAKE_CXX_FLAGS_DEBUG="-O0 -fuse-ld=lld" \
91+
-D CMAKE_EXPORT_COMPILE_COMMANDS=ON \
92+
-D TDESKTOP_API_TEST=ON \
93+
-D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF \
94+
-D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF
95+
96+
- name: Strip GCC-only flags from compile_commands.json.
97+
# Clang (used by IWYU) does not know -fhardened; it aborts the parse
98+
# of the command line before any analysis runs.
99+
run: sed -i 's/ -fhardened//g' out/compile_commands.json
100+
101+
- name: Run include-what-you-use.
102+
# The script body is materialised via a quoted heredoc so that any
103+
# special character in comments or strings (apostrophes, quotes,
104+
# backslashes) cannot break the outer `bash -ec '...'` quoting and
105+
# silently spill commands onto the host runner.
106+
run: |
107+
cat > iwyu.sh <<'SCRIPT'
108+
jq -r ".[].file | select(test(\"Telegram/SourceFiles/\"))" out/compile_commands.json > iwyu_files.txt
109+
echo "Analyzing $(wc -l < iwyu_files.txt) source files."
110+
# Bundled boost-*.imp files declare overlapping symbols with
111+
# incompatible visibility, which trips an assert in IWYU's
112+
# include picker on every translation unit. Skip them; tdesktop
113+
# does not depend on boost in Telegram/SourceFiles.
114+
MAPPINGS=""
115+
for f in /usr/local/share/include-what-you-use/*.imp; do
116+
[ -e "$f" ] || continue
117+
case "$(basename "$f")" in boost*) continue;; esac
118+
MAPPINGS="$MAPPINGS -Xiwyu --mapping_file=$f"
119+
done
120+
echo "Mapping files: $MAPPINGS"
121+
xargs -a iwyu_files.txt iwyu_tool.py -p out -j $(nproc) -- $MAPPINGS > iwyu.out 2>&1 || true
122+
# iwyu_tool.py masks per-file failures, so the diff stage cannot
123+
# tell "nothing to clean up" from "every file crashed". Require
124+
# at least one file to have produced a real IWYU verdict.
125+
# `grep -c` already prints 0 when nothing matches and exits 1, so
126+
# `|| echo 0` would append a second "0" and yield a multi-line value
127+
# that breaks the integer comparison below. `|| true` swallows the
128+
# non-zero exit without adding output; the parameter expansion below
129+
# then covers the case where iwyu.out is missing entirely.
130+
analyzed=$(grep -cE "should (add|remove) these lines|has correct #includes" iwyu.out 2>/dev/null || true)
131+
analyzed=${analyzed:-0}
132+
echo "IWYU produced verdicts for $analyzed file blocks."
133+
if [ "$analyzed" -eq 0 ]; then
134+
echo "::error::IWYU produced no usable analysis for any file; see iwyu-diagnostics artifact."
135+
exit 1
136+
fi
137+
fix_includes.py < iwyu.out || true
138+
SCRIPT
139+
docker run --rm \
140+
-u $(id -u) \
141+
-v $PWD:/usr/src/tdesktop \
142+
-w /usr/src/tdesktop \
143+
$IMAGE_TAG \
144+
bash -e iwyu.sh
145+
146+
- name: Upload diagnostics.
147+
if: always()
148+
uses: actions/upload-artifact@v7
149+
with:
150+
name: iwyu-diagnostics
151+
path: |
152+
iwyu.out
153+
iwyu_files.txt
154+
if-no-files-found: ignore
155+
156+
- name: Generate patch.
157+
id: diff
158+
run: |
159+
git diff -- Telegram/SourceFiles > iwyu.patch
160+
if [ -s iwyu.patch ]; then
161+
echo "has_changes=true" >> $GITHUB_OUTPUT
162+
echo "Patch size: $(wc -l < iwyu.patch) lines."
163+
git diff --stat -- Telegram/SourceFiles
164+
else
165+
echo "has_changes=false" >> $GITHUB_OUTPUT
166+
echo "No IWYU suggestions to apply, skipping."
167+
fi
168+
169+
- name: Upload patch artifact.
170+
if: steps.diff.outputs.has_changes == 'true'
171+
uses: actions/upload-artifact@v7
172+
with:
173+
name: iwyu-patch
174+
path: iwyu.patch
175+
176+
verify-linux:
177+
name: Verify Linux
178+
needs: generate
179+
if: needs.generate.outputs.has_changes == 'true'
180+
uses: ./.github/workflows/linux.yml
181+
with:
182+
ref: ${{ needs.generate.outputs.ref }}
183+
apply_patch: true
184+
patch_artifact: iwyu-patch
185+
force_depot: true
186+
upload_artifact: false
187+
188+
verify-mac:
189+
name: Verify macOS
190+
needs: generate
191+
if: needs.generate.outputs.has_changes == 'true'
192+
uses: ./.github/workflows/mac.yml
193+
with:
194+
ref: ${{ needs.generate.outputs.ref }}
195+
apply_patch: true
196+
patch_artifact: iwyu-patch
197+
force_depot: true
198+
upload_artifact: false
199+
200+
verify-win:
201+
name: Verify Windows
202+
needs: generate
203+
if: needs.generate.outputs.has_changes == 'true'
204+
uses: ./.github/workflows/win.yml
205+
with:
206+
ref: ${{ needs.generate.outputs.ref }}
207+
apply_patch: true
208+
patch_artifact: iwyu-patch
209+
force_depot: true
210+
upload_artifact: false
211+
212+
open-pr:
213+
name: Open pull request
214+
needs: [generate, verify-linux, verify-mac, verify-win]
215+
if: needs.generate.outputs.has_changes == 'true' && github.event_name != 'push'
216+
runs-on: ubuntu-latest
217+
218+
steps:
219+
- uses: actions/checkout@v6
220+
with:
221+
ref: ${{ needs.generate.outputs.ref }}
222+
fetch-depth: 0
223+
224+
- uses: actions/download-artifact@v5
225+
with:
226+
name: iwyu-patch
227+
path: ${{ runner.temp }}/iwyu
228+
229+
- name: Apply patch.
230+
run: git apply "${{ runner.temp }}/iwyu/iwyu.patch"
231+
232+
- name: Compute branch name.
233+
id: branch
234+
run: echo "name=iwyu/cleanup-$(date -u +%Y-%m)" >> $GITHUB_OUTPUT
235+
236+
- name: Create pull request.
237+
uses: peter-evans/create-pull-request@v7
238+
with:
239+
base: ${{ needs.generate.outputs.ref }}
240+
branch: ${{ steps.branch.outputs.name }}
241+
delete-branch: true
242+
commit-message: 'Drop unused includes detected by IWYU.'
243+
title: 'Drop unused includes (IWYU cleanup).'
244+
body: |
245+
Automated include-what-you-use cleanup of `Telegram/SourceFiles/`.
246+
247+
Verified to build on Linux, macOS and Windows by the upstream IWYU workflow run before this PR was opened:
248+
<https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}>
249+
250+
Note: GitHub does not auto-trigger PR checks for PRs created via `GITHUB_TOKEN`. Close and reopen this PR (or push an empty commit) to run the regular `linux.yml` / `mac.yml` / `win.yml` checks if you want to re-verify on the actual PR.

.github/workflows/win.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,14 @@ jobs:
6666

6767
windows:
6868
name: Windows
69-
runs-on: ${{ matrix.arch == 'arm64' && 'windows-11-arm' || ((inputs.force_depot || github.event_name == 'pull_request' || startsWith(github.ref, 'refs/tags/')) && 'depot-windows-latest-16' || 'windows-latest') }}
69+
runs-on: ${{ (inputs.force_depot || github.event_name == 'pull_request' || startsWith(github.ref, 'refs/tags/')) && 'depot-windows-latest-16' || 'windows-latest' }}
7070

7171
strategy:
7272
matrix:
73-
arch: [x64_x86, x64, arm64]
73+
arch: [x64_x86, x64]
7474
qt: ["", qt6]
7575
generator: ["", "Ninja Multi-Config"]
7676
exclude:
77-
- arch: arm64
78-
qt: ""
7977
- arch: x64_x86
8078
qt: qt6
8179

@@ -195,7 +193,6 @@ jobs:
195193
if [ -n "${{ matrix.arch }}" ]; then
196194
case "${{ matrix.arch }}" in
197195
x64_x86) ARCH="x86";;
198-
arm64) ARCH="arm";;
199196
*) ARCH="${{ matrix.arch }}";;
200197
esac
201198
echo "Architecture from matrix: $ARCH"

0 commit comments

Comments
 (0)