Skip to content

Commit fa13ef4

Browse files
Switch to an aggregated Changes system with much lower collision rates []
1 parent 625d8b7 commit fa13ef4

23 files changed

Lines changed: 1808 additions & 39 deletions

File tree

‎.agents/skills/edg-changes-example/SKILL.md‎

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
---
22
name: edg-changes-example
33
description: >-
4-
Encodes and decodes non-UTF-8 example bytes in Changes changelogs with
5-
edg-changes-example («HHHH...» markers) and writes Changes files as UTF-8.
6-
Use when editing any Changes file (src/Changes, util/Changes, …), adding
4+
Writes Changes entries as pending_changes/*.txt files (collected
5+
nightly by edg-collect-changes, checked with edg-collect-changes --check),
6+
and encodes/decodes non-UTF-8 example bytes with edg-changes-example
7+
(«HHHH...» markers). Use when adding a Changes entry, editing any Changes
8+
file (src/Changes, util/Changes, …) or pending_changes/ entry, adding
79
examples with Latin-1/EUC-JP/Shift-JIS/other non-UTF-8 bytes, or verifying
810
changelog encoding.
911
---
1012

11-
# `edg-changes-example` and Changes files
13+
# Changes entries, `edg-collect-changes`, and `edg-changes-example`
1214

1315
## Policy (all `Changes` files)
1416

@@ -74,7 +76,50 @@ bytes. No other escapes are interpreted.
7476

7577
## Workflow for a new changelog entry
7678

77-
1. Draft the entry as UTF-8 prose.
79+
New entries are **not** written into a `Changes` file. Each `Changes` file
80+
has a `pending_changes/` directory beside it (`src/pending_changes/`,
81+
`util/pending_changes/`, …); add one entry file there per change, named
82+
`*.txt` (suggested: `gh-<N>-<short-slug>.txt`). A nightly job
83+
(`.github/workflows/collect-changes.yml`, midnight US Eastern) runs
84+
`edg-collect-changes`, which moves every entry into its `Changes` file under
85+
the newest `Version x.y` line, adds the date, orders that night's entries by
86+
summary line, and deletes the entry files.
87+
88+
Entry file format:
89+
90+
```text
91+
//allowed_words: reflectable memoized
92+
[GH #335]
93+
Type transformations of qualified function types
94+
95+
Previously, the __add_lvalue_reference, __add_rvalue_reference, ...
96+
For example, with --c++11:
97+
98+
using F = void() const;
99+
using F = __add_pointer(F); // Previously a spurious error, now okay.
100+
```
101+
102+
- Optional leading `//key: value` directives (EDG C++ line directive
103+
syntax). `//allowed_words:` lists space-separated words the spell check
104+
should accept (identifiers, jargon); repeat the line as needed. Words the
105+
target `Changes` file already uses (`constexpr`, `lvalue`, …) are accepted
106+
without it. Directives are dropped when the entry is collected.
107+
- The tag block: one or more comma-separated `GH #N` tags in brackets
108+
(`[GH #12,GH #34]`; only `GH #N`, never `[]`). It may wrap onto several
109+
lines; the tool re-wraps it the way existing entries are wrapped.
110+
- **No date.** The tool adds it (`m/d/yy`, padded to 8 columns) in front of
111+
the tags.
112+
- The summary line, one blank line, then the description, in the same style
113+
as existing entries (unindented prose wrapped at 79 columns, two spaces
114+
after periods, examples indented 2 spaces).
115+
- UTF-8, no tabs, at most **79** columns per line. Trailing whitespace is
116+
tolerated (it's stripped on collection).
117+
118+
Steps:
119+
120+
1. Draft the entry as UTF-8 prose in
121+
`<dir>/pending_changes/<name>.txt` (the `pending_changes/` beside
122+
the `Changes` file the entry belongs in, usually `src/`).
78123
2. If an example needs non-UTF-8 bytes, author the example in a small raw
79124
file (or produce the markers by hand only when the bytes are already
80125
known), then run `edg-changes-example encode` and paste the UTF-8 result
@@ -83,20 +128,35 @@ bytes. No other escapes are interpreted.
83128

84129
`Note: The above example must be decoded using the edg-changes-example tool.`
85130

86-
4. Insert the entry into the appropriate `Changes` file with a **UTF-8**
87-
write (keep the rest of the file valid UTF-8).
88-
5. Verify the file still decodes as UTF-8 (raises on failure):
131+
4. Check the entry (format, spelling, typos, line length). This is the
132+
check `edg-check-file-changes` does for `pending_changes/*.txt` files,
133+
which pull request CI runs and which makes the pre-push hook refuse the
134+
push (no override) if anything is wrong:
89135

90136
```bash
91-
python3 -c "open('path/to/Changes', encoding='utf-8').read()"
137+
edg-exec -- edg-collect-changes --check src/Changes src/pending_changes
92138
```
93139

94-
Use the real path (for example `src/Changes`). A clean exit means the
95-
whole file is valid UTF-8; a `UnicodeDecodeError` means the write
96-
introduced non-UTF-8 bytes and must be fixed before continuing.
140+
(Name the `Changes` file and `pending_changes/` directory the entry is
141+
in. `edg-exec` runs it in the dev-env container, which has `aspell`.) For
142+
misspellings that are really identifiers or terms, add them to an
143+
`//allowed_words:` line at the very top of the entry, as the failure
144+
message shows; fix real misspellings instead.
145+
5. Optionally preview the result without changing anything:
146+
`edg-collect-changes --dry-run src/Changes src/pending_changes`.
147+
148+
Edit a `Changes` file directly only to correct an entry that has already
149+
been collected; then write it as **UTF-8** and verify the file still decodes
150+
(raises on failure):
151+
152+
```bash
153+
python3 -c "open('path/to/Changes', encoding='utf-8').read()"
154+
```
97155

98156
## Do not
99157

158+
- Add new entries directly to a `Changes` file, or put a date in a
159+
`pending_changes/` entry.
100160
- Commit raw Latin-1 / Shift-JIS / etc. bytes inside a `Changes` file.
101161
- Invent alternate note wording; match the existing sentence above.
102162
- Run `encode` on the entire historical `src/Changes` and rewrite it unless

‎.agents/skills/edg-cpfe-frontend/SKILL.md‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,19 @@ Language: `--c++11` … `--c++26`. Emulation: `--gnu=XXYYZZ`,
4545

4646
## Editing `Changes` files
4747

48-
Write every `Changes` file as **UTF-8** (`src/Changes`, `util/Changes`, and
49-
any other `Changes` in the tree). For non-UTF-8 example bytes, `«HHHH…»`
50-
markers, the required note line, encode/decode commands, and verification,
51-
follow skill **edg-changes-example** — do not invent a parallel procedure here.
48+
Add new entries as `pending_changes/*.txt` files beside the `Changes`
49+
file (usually `src/pending_changes/`), not in the `Changes` file itself; a
50+
nightly job collects them with `edg-collect-changes`. Write everything as
51+
**UTF-8**. For the entry format, `//allowed_words:`, `edg-collect-changes
52+
--check`, non-UTF-8 example bytes (`«HHHH…»` markers and the note line), and
53+
verification, follow skill **edg-changes-example** — do not invent a parallel
54+
procedure here.
5255

5356
## Related skills
5457

5558
- **edg-cpfe-style** — coding style; [code_style.rst](../../../doc/source/code_style.rst).
56-
- **edg-changes-example** — UTF-8 Changes writes; `edg-changes-example` CLI.
59+
- **edg-changes-example** — Changes entries (`pending_changes/`), UTF-8;
60+
`edg-collect-changes` and `edg-changes-example` CLIs.
5761
- **edg-cpfe-build-test** — rebuild, `edg-docker-test`, recording.
5862
- **edg-cpfe-bisect** — `edg-docker-test-bisect` between good/bad commits.
5963
- Do not invent a separate defect-tracker workflow; use the project's current

‎.git-hooks/pre-push.py‎

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import sys
4343
import tempfile
4444

45+
import edgchanges
4546
import edgutil
4647

4748
from pathlib import Path
@@ -170,6 +171,11 @@ def confirm_okay(self):
170171
print('Too many attempts.')
171172
sys.exit(1)
172173

174+
def reject(self):
175+
'''Record a problem that can't be accepted, without asking.'''
176+
print(' Not allowed: CI would reject this; fix it and push again.')
177+
self.errors = 1
178+
173179
def check_commits(self):
174180
'''Walk commits until one already on a remote branch is found.
175181
@@ -287,6 +293,23 @@ def check_changed_files(self, first_new_commit):
287293
for file_path_str, file_results in results.items():
288294
print(f" Checking file: {file_path_str}")
289295

296+
# A pending Changes entry with any of these problems fails the
297+
# changes-fragments CI check, so there's no accepting them here.
298+
is_changes_entry = edgchanges.is_fragment_path(file_path_str)
299+
confirm_okay = (
300+
self.reject if is_changes_entry else self.confirm_okay
301+
)
302+
303+
format_errors = [
304+
edgchanges.FormatError(*error)
305+
for error in file_results['format_errors']
306+
]
307+
if len(format_errors) != 0:
308+
print(' Badly formatted Changes entry:')
309+
for error in format_errors:
310+
print(f" - {edgchanges.describe_error(file_path_str, error)}")
311+
confirm_okay()
312+
290313
misspellings = file_results['misspellings']
291314
if misspellings is None:
292315
print(' Spell check failed:')
@@ -297,14 +320,20 @@ def check_changed_files(self, first_new_commit):
297320
print(' New misspelled words:')
298321
for misspelling in misspellings:
299322
print(f" - {misspelling}")
300-
self.confirm_okay()
323+
if is_changes_entry:
324+
hint_lines = edgchanges.allowed_words_hint(
325+
file_path_str,
326+
misspellings
327+
)
328+
print_indented('\n'.join(hint_lines), ' ')
329+
confirm_okay()
301330

302331
typos = file_results['typos']
303332
if len(typos) != 0:
304333
print(' New typos:')
305334
for typo in typos:
306335
print(f" - {typo}")
307-
self.confirm_okay()
336+
confirm_okay()
308337

309338
coding_errors = file_results['coding_errors']
310339
if len(coding_errors) != 0:
@@ -327,14 +356,9 @@ def check_changed_files(self, first_new_commit):
327356

328357
overlong_lines = file_results['overlong_lines']
329358
if len(overlong_lines) != 0:
330-
for line_no, (line_start, lines) in overlong_lines.items():
331-
print(f" Line {line_no} too long:")
332-
line_end = line_start + (len(lines) - 1)
333-
print(f" {line_start} -> {line_end} ".center(79, '='))
334-
for line in lines:
335-
print(line, end = '')
336-
print('=' * 79)
337-
self.confirm_okay()
359+
for line in edgutil.format_overlong_lines(overlong_lines, ' '):
360+
print(line)
361+
confirm_okay()
338362

339363
def run(self) -> bool:
340364
'''Execute the full pre-push check sequence.'''

‎.github/workflows/build-and-test-ci.yml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ on:
3030
push:
3131
branches:
3232
- main
33+
# The nightly collect-changes job's commits only move Changes entries.
34+
paths-ignore:
35+
- '**/Changes'
36+
- '**/pending_changes/**'
3337
pull_request:
3438

3539
concurrency:
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Part of the EDG Compiler Project, under the Apache License v2.0 with LLVM
2+
# Exceptions.
3+
# See https://edgcpp.org/LICENSE.txt for license information.
4+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
#
6+
# Check the pending Changes entries (*/pending_changes/*.txt) with
7+
# `edg-collect-changes --check` (format, spelling, typos, line length), so a
8+
# bad entry is caught before the nightly collect-changes job meets it, and run
9+
# the unit tests of the tools involved.
10+
11+
name: Pending Changes Entries
12+
13+
on:
14+
push:
15+
branches:
16+
- main
17+
paths:
18+
- '**/pending_changes/**'
19+
- .github/workflows/changes-fragments.yml
20+
- dev_tools/bin/edg-check-file-changes
21+
- dev_tools/bin/edg-collect-changes
22+
- dev_tools/pylibs/edgchanges/**
23+
- dev_tools/pylibs/edgutil/**
24+
- dev_tools/tests/**
25+
pull_request:
26+
paths:
27+
- '**/pending_changes/**'
28+
- .github/workflows/changes-fragments.yml
29+
- dev_tools/bin/edg-check-file-changes
30+
- dev_tools/bin/edg-collect-changes
31+
- dev_tools/pylibs/edgchanges/**
32+
- dev_tools/pylibs/edgutil/**
33+
- dev_tools/tests/**
34+
35+
permissions:
36+
contents: read
37+
38+
jobs:
39+
check:
40+
name: check-pending-changes
41+
runs-on: ubuntu-latest
42+
timeout-minutes: 10
43+
env:
44+
PYTHONPATH: ${{ github.workspace }}/dev_tools/pylibs
45+
# Each holds a Changes file and its pending_changes/ directory (keep in
46+
# step with the list in collect-changes.yml).
47+
CHANGES_DIRS: src util lib_src include_c++ nt_util
48+
steps:
49+
- name: Check out repository
50+
uses: actions/checkout@v7
51+
52+
# The same dictionary as the dev-env image
53+
# (dev_tools/docker/dev-env/setup-scripts/install-software.sh).
54+
- name: Install aspell
55+
run: |
56+
sudo apt-get update
57+
sudo apt-get install -y aspell aspell-en
58+
59+
- name: Run unit tests
60+
run: python3 -m unittest discover -s dev_tools/tests -v
61+
62+
- name: Check pending Changes entries
63+
run: |
64+
status=0
65+
for dir in ${CHANGES_DIRS}; do
66+
dev_tools/bin/edg-collect-changes --check \
67+
"${dir}/Changes" "${dir}/pending_changes" || status=1
68+
done
69+
exit "${status}"

0 commit comments

Comments
 (0)