Skip to content

Commit a04e511

Browse files
[github] Add CODEOWNERS sync support (#67) (#127)
* [github] Add CODEOWNERS sync support (#67) * [github] Refine CODEOWNERS inference rules (#67) * [github] Rename CODEOWNERS template resource (#67) * [github] Record project CODEOWNERS metadata (#67) * [github] Normalize CODEOWNERS template formatting (#67) * [github] Normalize CODEOWNERS command syntax (#67) * Update wiki submodule pointer for PR #127 --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent a12129f commit a04e511

18 files changed

Lines changed: 1046 additions & 26 deletions

.github/CODEOWNERS

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Generated by fast-forward/dev-tools
2+
#
3+
# Review the generated owners before committing this file.
4+
#
5+
# When no GitHub owners can be inferred automatically, replace the placeholder
6+
# example below with the usernames, teams, or emails that should review
7+
# changes in the consumer repository.
8+
#
9+
# Example:
10+
# * @your-github-user @your-org/platform-team
11+
12+
* @php-fast-forward @coisa

.github/wiki

Submodule wiki updated from a4cb5e6 to 831e581

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add CODEOWNERS generation and sync support for consumer repositories (#67)
13+
1014
## [1.13.0] - 2026-04-19
1115

1216
### Added

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ across Fast Forward libraries.
2727
version inference, release promotion, and release-note rendering commands
2828
- Ships shared workflow stubs, `.editorconfig`, Dependabot configuration, and
2929
other onboarding defaults for consumer repositories
30+
- Generates `.github/CODEOWNERS` files from local project metadata instead of
31+
shipping repository-specific owners into consumers
3032
- Synchronizes packaged agent skills into consumer `.agents/skills`
3133
directories using safe link-based updates
3234
- Works both as a Composer plugin and as a local binary
@@ -111,6 +113,10 @@ composer skills
111113
composer funding
112114
composer funding --dry-run
113115

116+
# Generate .github/CODEOWNERS from composer.json metadata
117+
composer codeowners
118+
composer codeowners --interactive
119+
114120
# Merges and synchronizes .gitignore files
115121
composer gitignore
116122

@@ -163,6 +169,11 @@ with `.github/FUNDING.yml`, including GitHub Sponsors handles and `custom`
163169
URLs, while preserving unsupported providers in place and re-running
164170
`composer normalize` after manifest updates.
165171

172+
The `codeowners` command generates `.github/CODEOWNERS` from local
173+
`composer.json` metadata. It prefers explicit GitHub profile URLs from author
174+
metadata, falls back to commented suggestions from support metadata, and can
175+
prompt for owners when `--interactive` is used in a terminal.
176+
166177
The `skills` command keeps `.agents/skills` aligned with the packaged Fast
167178
Forward skill set. It creates missing links, repairs broken links, and
168179
preserves existing non-symlink directories. The `dev-tools:sync` command calls
@@ -203,8 +214,9 @@ source of truth.
203214
| `composer docs` | Builds the HTML documentation site from PSR-4 code and `docs/`. |
204215
| `composer skills` | Creates or repairs packaged skill links in `.agents/skills`. |
205216
| `composer funding` | Synchronizes managed funding metadata between `composer.json` and `.github/FUNDING.yml`. |
217+
| `composer codeowners` | Generates managed `.github/CODEOWNERS` content from local repository metadata. |
206218
| `composer gitattributes` | Manages export-ignore rules in `.gitattributes`. |
207-
| `composer dev-tools:sync` | Updates scripts, funding metadata, workflow stubs, `.editorconfig`, `.gitignore`, `.gitattributes`, wiki setup, and packaged skills. |
219+
| `composer dev-tools:sync` | Updates scripts, CODEOWNERS, funding metadata, workflow stubs, `.editorconfig`, `.gitignore`, `.gitattributes`, wiki setup, and packaged skills. |
208220

209221
## 🔌 Integration
210222

@@ -228,9 +240,9 @@ so agents can discover the packaged skills shipped with this repository.
228240
orchestration commands such as `standards` dispatch other commands through
229241
the console application itself.
230242
- `Consumer Sync Pipeline` - `dev-tools:sync` refreshes `composer.json`,
231-
funding metadata, workflow stubs, repository defaults, git metadata files,
232-
packaged Git hooks, and, in normal mode, the wiki submodule plus packaged
233-
skills.
243+
CODEOWNERS, funding metadata, workflow stubs, repository defaults, git
244+
metadata files, packaged Git hooks, and, in normal mode, the wiki submodule
245+
plus packaged skills.
234246

235247
## 🤝 Contributing
236248

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
"authors": [
1717
{
1818
"name": "Felipe Sayão Lobato Abreu",
19-
"email": "github@mentordosnerds.com"
19+
"email": "github@mentordosnerds.com",
20+
"homepage": "https://github.com/coisa",
21+
"role": "Maintainer"
2022
}
2123
],
2224
"homepage": "https://github.com/php-fast-forward/",

docs/api/commands.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ subprocess execution is needed.
6666
* - ``FastForward\DevTools\Console\Command\FundingCommand``
6767
- ``funding``
6868
- Synchronizes managed funding metadata between Composer and GitHub files.
69+
* - ``FastForward\DevTools\Console\Command\CodeOwnersCommand``
70+
- ``codeowners``
71+
- Generates managed ``.github/CODEOWNERS`` content from project metadata.
6972
* - ``FastForward\DevTools\Console\Command\SyncCommand``
7073
- ``dev-tools:sync``
7174
- Synchronizes consumer-facing scripts, automation assets, and packaged

docs/commands/codeowners.rst

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
codeowners
2+
==========
3+
4+
Generates ``.github/CODEOWNERS`` from local repository metadata.
5+
6+
Description
7+
-----------
8+
9+
The ``codeowners`` command creates or refreshes a managed ``CODEOWNERS`` file
10+
for the current repository. It prefers explicit GitHub profile URLs from
11+
``composer.json`` authors metadata, falls back to commented suggestions from
12+
``composer.json`` support metadata, and can prompt for owners when interactive
13+
input is enabled.
14+
15+
Usage
16+
-----
17+
18+
.. code-block:: bash
19+
20+
composer codeowners
21+
composer codeowners [options]
22+
23+
Options
24+
-------
25+
26+
``--file``
27+
Target path to manage. Defaults to ``.github/CODEOWNERS``.
28+
29+
``--overwrite, -o``
30+
Replace an existing CODEOWNERS file instead of preserving it.
31+
32+
``--dry-run``
33+
Preview managed-file drift without writing changes.
34+
35+
``--check``
36+
Report managed-file drift and exit with code ``1`` when CODEOWNERS needs an
37+
update.
38+
39+
``--interactive``
40+
Prompt for owners when metadata inference is insufficient and confirm before
41+
replacing an existing file.
42+
43+
Examples
44+
--------
45+
46+
Generate CODEOWNERS from the current repository metadata:
47+
48+
.. code-block:: bash
49+
50+
composer codeowners
51+
52+
Preview drift without writing:
53+
54+
.. code-block:: bash
55+
56+
composer codeowners --dry-run
57+
58+
Fail in CI when CODEOWNERS needs an update:
59+
60+
.. code-block:: bash
61+
62+
composer codeowners --check
63+
64+
Prompt for explicit owners when metadata is incomplete:
65+
66+
.. code-block:: bash
67+
68+
composer codeowners --interactive
69+
70+
Behavior
71+
--------
72+
73+
- It reads author homepages from ``composer.json`` and converts GitHub profile
74+
URLs into ``@owner`` handles.
75+
- When direct owners cannot be inferred, it uses ``composer.json`` support
76+
metadata to add a commented suggestion instead of writing someone else's
77+
ownership rules into the consumer repository.
78+
- In interactive terminals, ``--interactive`` lets maintainers provide
79+
space-separated owners for the catch-all ``*`` rule before writing the file.
80+
- By default, an existing ``.github/CODEOWNERS`` file is preserved unless
81+
``--overwrite``, ``--dry-run``, ``--check``, or ``--interactive`` is used.

docs/commands/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Detailed documentation for each dev-tools command.
2020
skills
2121
sync
2222
funding
23+
codeowners
2324
gitignore
2425
gitattributes
2526
license

docs/commands/sync.rst

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ The ``dev-tools:sync`` command synchronizes consumer-facing automation and defau
1212
2. ``copy-resource`` - copies GitHub Actions workflows, including changelog automation
1313
3. ``copy-resource`` - copies .editorconfig
1414
4. ``copy-resource`` - copies dependabot.yml
15-
5. ``funding`` - synchronizes ``composer.json`` funding metadata with ``.github/FUNDING.yml``
16-
6. ``wiki --init`` - initializes wiki as submodule
17-
7. ``gitignore`` - merges .gitignore files
18-
8. ``gitattributes`` - manages export-ignore rules
19-
9. ``skills`` - synchronizes packaged skills
20-
10. ``license`` - generates LICENSE file
21-
11. ``git-hooks`` - installs Git hooks
15+
5. ``codeowners`` - generates ``.github/CODEOWNERS`` from local metadata
16+
6. ``funding`` - synchronizes ``composer.json`` funding metadata with ``.github/FUNDING.yml``
17+
7. ``wiki --init`` - initializes wiki as submodule
18+
8. ``gitignore`` - merges .gitignore files
19+
9. ``gitattributes`` - manages export-ignore rules
20+
10. ``skills`` - synchronizes packaged skills
21+
11. ``license`` - generates LICENSE file
22+
12. ``git-hooks`` - installs Git hooks
2223

2324
Usage
2425
-----
@@ -27,7 +28,6 @@ Usage
2728
2829
composer dev-tools:sync
2930
composer dev-tools:sync [options]
30-
vendor/bin/dev-tools dev-tools:sync [options]
3131
3232
Options
3333
-------
@@ -90,17 +90,20 @@ Exit Codes
9090
Behavior
9191
---------
9292

93-
- Updates ``composer.json`` scripts, extra configuration, and managed funding
94-
metadata.
93+
- Updates ``composer.json`` scripts, extra configuration, managed funding
94+
metadata, and managed ``.github/CODEOWNERS`` content.
9595
- Copies missing workflow stubs, including tests, reports, wiki, and changelog
9696
automation, plus ``.editorconfig`` and ``dependabot.yml``.
97+
- Generates ``.github/CODEOWNERS`` from local metadata and preserves existing
98+
ownership rules by default unless ``--overwrite`` or an explicit preview
99+
mode is used.
97100
- Synchronizes supported funding metadata between ``composer.json`` and
98101
``.github/FUNDING.yml``.
99102
- When ``--overwrite`` is enabled, replaced text resources emit a unified diff
100103
so terminal sessions and CI logs show what changed.
101104
- ``--dry-run`` and ``--check`` verify managed-file drift for ``composer.json``,
102-
funding metadata, copied resources, ``.gitignore``, ``.gitattributes``,
103-
``LICENSE``, and Git hooks.
105+
``.github/CODEOWNERS``, funding metadata, copied resources, ``.gitignore``,
106+
``.gitattributes``, ``LICENSE``, and Git hooks.
104107
- ``--interactive`` prompts before replacing drifted managed files when the
105108
command is running in an interactive terminal.
106109
- Creates ``.github/wiki`` as a git submodule when missing.

docs/running/specialized-commands.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,28 @@ Important details:
239239
- it supports ``--dry-run``, ``--check``, and ``--interactive`` so funding
240240
drift can be surfaced in CI and reviewed locally.
241241

242+
``codeowners``
243+
--------------
244+
245+
Generates managed CODEOWNERS files from repository metadata.
246+
247+
.. code-block:: bash
248+
249+
composer codeowners
250+
composer codeowners --dry-run
251+
composer codeowners --interactive
252+
253+
Important details:
254+
255+
- it inspects ``composer.json`` author homepages to infer GitHub handles for
256+
``.github/CODEOWNERS``;
257+
- when direct ownership cannot be inferred, it renders a commented fallback
258+
instead of copying hard-coded owners into the consumer repository;
259+
- ``--interactive`` lets maintainers provide explicit owners before writing the
260+
catch-all ``*`` rule;
261+
- ``dev-tools:sync`` runs ``codeowners`` automatically alongside the other
262+
consumer bootstrap steps.
263+
242264
``dev-tools:sync``
243265
------------------
244266

@@ -255,6 +277,8 @@ Important details:
255277
- it calls ``funding`` so supported funding metadata stays aligned between
256278
``composer.json`` and ``.github/FUNDING.yml``;
257279
- it copies missing workflow stubs, ``.editorconfig``, and ``dependabot.yml``;
280+
- it calls ``codeowners`` to generate ``.github/CODEOWNERS`` from local
281+
metadata;
258282
- it creates ``.github/wiki`` as a git submodule when the directory is
259283
missing.
260284
- it calls ``gitignore`` to merge the canonical .gitignore with the project's

0 commit comments

Comments
 (0)