From a286666dfca2300fffca1ab0d3517b6294ec2c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Say=C3=A3o=20Lobato=20Abreu?= Date: Tue, 13 Oct 2026 04:20:06 -0300 Subject: [PATCH 1/3] fix(wiki): publish directly and avoid automatic submodule initialization --- .github/wiki | 1 - .github/workflows/wiki-direct.yml | 114 ++++++++++++++++++ .github/workflows/wiki-maintenance-entry.yml | 20 +-- .github/workflows/wiki.yml | 20 ++- .gitmodules | 6 - AGENTS.md | 13 +- CHANGELOG.md | 3 +- README.md | 14 ++- docs/commands/sync.rst | 9 +- docs/commands/wiki.rst | 10 +- docs/internals/architecture.rst | 5 +- docs/usage/github-actions.rst | 82 +++++++------ resources/github-actions/wiki-maintenance.yml | 26 +--- resources/github-actions/wiki.yml | 25 ++-- src/Console/Command/SyncCommand.php | 7 +- tests/Console/Command/SyncCommandTest.php | 16 ++- 16 files changed, 241 insertions(+), 130 deletions(-) delete mode 160000 .github/wiki create mode 100644 .github/workflows/wiki-direct.yml delete mode 100644 .gitmodules diff --git a/.github/wiki b/.github/wiki deleted file mode 160000 index 961cfbb2e6..0000000000 --- a/.github/wiki +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 961cfbb2e6dffeba2a77ad64cbce45c3cda903b5 diff --git a/.github/workflows/wiki-direct.yml b/.github/workflows/wiki-direct.yml new file mode 100644 index 0000000000..8916ff09ef --- /dev/null +++ b/.github/workflows/wiki-direct.yml @@ -0,0 +1,114 @@ +name: Publish Wiki Directly + +on: + workflow_call: + +permissions: + contents: read + +jobs: + generate: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + persist-credentials: false + - name: Checkout the shared dev-tools actions + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + repository: php-fast-forward/dev-tools + ref: d5a3b7eec9896f9ea50974ff09b23c32887acbc0 + path: .dev-tools-actions + persist-credentials: false + - name: Resolve PHP version + id: php + uses: ./.dev-tools-actions/.github/actions/php/resolve-version + - name: Select the same pinned renderer + run: | + php <<'PHP' + 'path', + 'url' => '.dev-tools-actions', + 'options' => ['symlink' => false, 'versions' => ['fast-forward/dev-tools' => 'dev-main']], + ]; + } + $data['config']['allow-plugins']['fast-forward/dev-tools'] = false; + file_put_contents($file, json_encode($data, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT)); + PHP + - name: Setup PHP and dependencies + uses: ./.dev-tools-actions/.github/actions/php/setup-composer + with: + php-version: ${{ steps.php.outputs.php-version }} + root-version: dev-main + - name: Generate API pages + run: | + if [ "$GITHUB_REPOSITORY" = php-fast-forward/dev-tools ]; then + ./bin/dev-tools wiki --target=.dev-tools/wiki-generated --cache-dir="${RUNNER_TEMP}/wiki-phpdoc-cache" + else + dev-tools wiki --target=.dev-tools/wiki-generated --cache-dir="${RUNNER_TEMP}/wiki-phpdoc-cache" + fi + test -s .dev-tools/wiki-generated/Home.md + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: wiki + path: .dev-tools/wiki-generated + if-no-files-found: error + + publish: + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + needs: generate + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + concurrency: + group: ${{ github.repository }}-wiki-publication + cancel-in-progress: false + queue: max + steps: + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: wiki + path: wiki-generated + - name: Publish API pages + env: + GH_TOKEN: ${{ github.token }} + run: | + current=$(gh api "repos/${GITHUB_REPOSITORY}/commits/main" --jq .sha) + if [ "$current" != "$GITHUB_SHA" ]; then + echo 'A newer main run will publish the current documentation.' + exit 0 + fi + git -c credential.helper= -c 'credential.helper=!gh auth git-credential' clone "https://github.com/${GITHUB_REPOSITORY}.wiki.git" wiki + if find wiki-generated wiki -path wiki/.git -prune -o \( -type l -o -name AGENTS.md \) -print -quit | grep -q .; then + echo 'Unexpected symlink or agent instruction page.' >&2 + exit 1 + fi + if find wiki-generated -type f ! -name '*.md' -print -quit | grep -q .; then + echo 'Generated Wiki payload must contain only Markdown.' >&2 + exit 1 + fi + # classes/ and functions/ are phpDocumentor-owned API namespaces. + # Pages outside those namespaces are preserved. + for namespace in classes functions; do + mkdir -p "wiki-generated/${namespace}" "wiki/${namespace}" + rsync -a --delete "wiki-generated/${namespace}/" "wiki/${namespace}/" + done + cp wiki-generated/Home.md wiki/Home.md + git -C wiki add --all + if ! git -C wiki diff --cached --quiet; then + git -C wiki config user.name 'github-actions[bot]' + git -C wiki config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git -C wiki commit -m "Update Wiki from ${GITHUB_SHA}" + current=$(gh api "repos/${GITHUB_REPOSITORY}/commits/main" --jq .sha) + if [ "$current" != "$GITHUB_SHA" ]; then + echo 'Main advanced during generation; skip outdated publication.' + exit 0 + fi + git -C wiki -c credential.helper= -c 'credential.helper=!gh auth git-credential' push origin HEAD + fi diff --git a/.github/workflows/wiki-maintenance-entry.yml b/.github/workflows/wiki-maintenance-entry.yml index 7a1eb3ea65..810133c577 100644 --- a/.github/workflows/wiki-maintenance-entry.yml +++ b/.github/workflows/wiki-maintenance-entry.yml @@ -1,20 +1,12 @@ -name: Maintain Wiki +name: Legacy Wiki Maintenance on: workflow_dispatch: - schedule: - - cron: '17 3 * * *' - pull_request_target: - types: [closed] -concurrency: - group: update-wiki-maintenance-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true +permissions: {} jobs: - maintenance: - permissions: - contents: write - pull-requests: read - uses: ./.github/workflows/wiki-maintenance.yml - secrets: inherit + migration: + runs-on: ubuntu-latest + steps: + - run: echo 'Wiki publication now runs through wiki.yml without a submodule.' diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 48995515ae..79c8bd666c 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -1,18 +1,14 @@ -name: Update Wiki +name: Fast Forward Wiki Update on: + push: + branches: [main] pull_request: - types: [opened, synchronize, reopened] + workflow_dispatch: -concurrency: - group: update-wiki-preview-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true +permissions: + contents: write # Ceiling for the isolated publisher; generation remains read-only. jobs: - preview: - permissions: - actions: write - contents: write - pull-requests: read - uses: ./.github/workflows/wiki-preview.yml - secrets: inherit + wiki: + uses: ./.github/workflows/wiki-direct.yml diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 6242268e54..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "docs/wiki"] - path = .github/wiki - url = https://github.com/php-fast-forward/dev-tools.wiki.git -[submodule ".github/wiki"] - path = .github/wiki - url = https://github.com/php-fast-forward/dev-tools.wiki.git diff --git a/AGENTS.md b/AGENTS.md index 8f6ab441ca..3957adfc54 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -158,7 +158,7 @@ other managed assets through `composer dev-tools:sync`. Release and publishing behavior is driven primarily through `.github/workflows/tests.yml`, `changelog.yml`, `reports.yml`, `wiki.yml`, -`wiki-preview.yml`, `wiki-maintenance.yml`, `auto-assign.yml`, and +`wiki-direct.yml`, `auto-assign.yml`, and `label-sync.yml`, with reusable local workflow building blocks grouped under `.github/actions/` and packaged consumer workflow wrappers living under `resources/github-actions/`. Contract-specific templates in @@ -167,6 +167,11 @@ installed by `dev-tools:sync`; read each companion guide before copying one into a consumer repository. Packaged skills live under `.agents/skills/` alongside mirrored project-agent prompts under `.agents/agents/`. +The active `wiki.yml` entry and packaged wrapper call `wiki-direct.yml` for +read-only generation on pull requests and direct publication from `main`. +The maintenance entry is manual-only compatibility guidance; legacy reusable +`wiki-preview.yml` and `wiki-maintenance.yml` remain for unmigrated callers. + **Package Details:** - Type: `composer-plugin` @@ -198,7 +203,7 @@ composer dev-tools - `README.md`: high-level command surface, architecture overview, and consumer-facing context - `docs/commands/`: command-specific behavior and option details - `docs/usage/` and `docs/internals/`: workflow, reporting, release, and implementation notes -- `.github/workflows/`: CI and release automation truth, especially `tests.yml`, `reports.yml`, `review.yml`, `wiki.yml`, `wiki-preview.yml`, `wiki-maintenance.yml`, `changelog.yml`, `auto-assign.yml`, and `label-sync.yml` +- `.github/workflows/`: CI and release automation truth, especially `tests.yml`, `reports.yml`, `review.yml`, `wiki.yml`, `wiki-direct.yml`, `changelog.yml`, `auto-assign.yml`, and `label-sync.yml` - `.github/actions/`: shared workflow building blocks for `php`, `project-board`, `github-pages`, `review`, `summary`, `wiki`, `changelog`, and `label-sync` - `resources/github-actions/`: consumer-facing workflow wrappers synchronized by `dev-tools:sync` - [resources/github-actions-optional/test-statuses.md](resources/github-actions-optional/test-statuses.md): explicit opt-in guide for Dependabot status aliases; verify source workflow identity, PHP matrix and protection contexts before adopting the checkout-free template @@ -206,14 +211,14 @@ composer dev-tools - `src/Sync/`: shared packaged-directory synchronization primitives used by `skills` and `agents` - `.agents/skills/`: packaged procedural skills shipped to consumer repositories - `.agents/agents/`: repository-specific role prompts mirrored through `.github/agents` -- `.github/wiki`: generated or synchronized wiki content published by repo workflows +- `.dev-tools/wiki-generated`: local Markdown output from normal sync; wiki publication operates on a separate artifact and Wiki checkout ## Additional Notes - **GrumPHP**: Automatically runs on pre-commit (configured in `grumphp.yml`) - **Rector**: Custom rules in `src/Rector/` for automated refactoring - **Documentation**: Sphinx-based docs in `docs/` directory -- **Wiki**: Pull-request preview publication starts in `.github/workflows/wiki.yml`, while merged publication and preview cleanup run through `.github/workflows/wiki-maintenance.yml` +- **Wiki**: `.github/workflows/wiki.yml` delegates to `wiki-direct.yml`; pull requests generate without write credentials and only `main` publishes to the separate Wiki repository. `Home.md`, `classes/` and `functions/` are generated; preserve manually maintained pages outside those surfaces. Normal sync does not initialize a Wiki submodule; `wiki --init` remains an explicit legacy option. - **GitHub Actions**: Reusable workflows live in `.github/workflows/`, local workflow actions live in `.github/actions/`, and consumer wrappers are synchronized from `resources/github-actions/` - **Dependency Health CI**: `.github/workflows/tests.yml` always runs the dependency-health job, and its default `max-outdated` input is `-1` so outdated packages are reported without failing CI on count alone - **Sync Preview Modes**: `dev-tools:sync --dry-run`, `--check`, and `--interactive` intentionally skip wiki, skills, and agents because those flows do not yet expose non-destructive verification diff --git a/CHANGELOG.md b/CHANGELOG.md index 27df2a735f..1a7199cc61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,11 +18,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Composer(deps): Update ergebnis/phpunit-agent-reporter requirement from ^0.3 to ^1.0 (#356) - GitHub Actions(deps): Bump actions/checkout from 6 to 7 (#354) - GitHub Actions(deps): Bump EndBug/add-and-commit from 10 to 11 (#358) +- Publish generated API pages directly to the GitHub Wiki from main without parent submodule-pointer commits, while pull requests generate read-only artifacts. +- Generate local wiki Markdown in .dev-tools/wiki-generated during normal sync instead of initializing a Wiki submodule; retain explicit wiki --init for legacy use. ### Fixed - Isolate native Pages PR builds from production deployment queues, preserve full repository history in generated metrics, and retry downloaded identity hashes during CDN propagation. - - Keep required per-version statuses current across normal and Dependabot reruns through checkout-free lifecycle publishers using verified GitHub run and job metadata. - Keep Composer audit and nested dependency-health checks plugin-free after CI installs without plugins, so consumer allowlists do not block vulnerability or dependency analysis. - Isolate completed per-version status publication from repository-controlled test jobs, preserve access to private GitHub job metadata, and disable persisted checkout credentials in the reusable test workflow. diff --git a/README.md b/README.md index 86a2e3a130..9fcb157906 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ composer update-composer-json --force # Installs and synchronizes dev-tools scripts, GitHub Actions workflows, # .editorconfig, .gitignore rules, packaged skills, packaged agents, and the -# repository wiki submodule in .github/wiki +# local wiki Markdown in .dev-tools/wiki-generated composer dev-tools:sync ``` @@ -193,6 +193,14 @@ to synthesize API pages. When `.github/wiki` is absent and no wiki has been initialized yet, `wiki` now skips generation with a warning instead of failing the whole automation run. +Normal `dev-tools:sync` generates local Markdown in `.dev-tools/wiki-generated` +without creating a Git submodule. The packaged `wiki.yml` workflow publishes +generated API pages directly to the GitHub Wiki from `main`; pull requests +generate a read-only artifact. Existing workflow wrappers require an explicit +migration or `composer dev-tools:sync --overwrite` to adopt these changes. See +[the workflow guide](docs/usage/github-actions.rst) for publication and page +ownership details. + The changelog commands manage Keep a Changelog 1.1.0 files without requiring extra tooling in the consumer repository. `changelog:entry` bootstraps a missing changelog file on first use, `changelog:check` enforces meaningful @@ -329,7 +337,7 @@ skills they depend on. | `composer funding` | Synchronizes managed funding metadata between `composer.json` and `.github/FUNDING.yml`. | | `composer codeowners` | Generates managed `.github/CODEOWNERS` content from local repository metadata. | | `composer gitattributes` | Manages export-ignore rules in `.gitattributes`. | -| `composer dev-tools:sync` | Updates scripts, CODEOWNERS, funding metadata, workflow stubs, `.editorconfig`, `.gitignore`, `.gitattributes`, wiki setup, packaged skills, and packaged agents. | +| `composer dev-tools:sync` | Updates scripts, CODEOWNERS, funding metadata, workflow stubs, `.editorconfig`, `.gitignore`, `.gitattributes`, local wiki Markdown, packaged skills, and packaged agents. | | `vendor/bin/dev-tools self-update` / `composer dev-tools:self-update` | Updates the local DevTools package, or the Composer global installation when the active binary is globally installed. | `--working-dir`/`-d` changes the project root used by the standalone binary. @@ -370,7 +378,7 @@ authoring. the console application itself. - `Consumer Sync Pipeline` - `dev-tools:sync` refreshes `composer.json`, CODEOWNERS, funding metadata, workflow stubs, repository defaults, git - metadata files, packaged Git hooks, and, in normal mode, the wiki submodule + metadata files, packaged Git hooks, and, in normal mode, local wiki Markdown plus packaged skills and packaged project agents. ## 🤝 Contributing diff --git a/docs/commands/sync.rst b/docs/commands/sync.rst index 027a84b75f..f6598d7449 100644 --- a/docs/commands/sync.rst +++ b/docs/commands/sync.rst @@ -14,7 +14,7 @@ The ``dev-tools:sync`` command synchronizes consumer-facing automation and defau 4. ``copy-resource`` - copies dependabot.yml 5. ``codeowners`` - generates ``.github/CODEOWNERS`` from local metadata 6. ``funding`` - synchronizes ``composer.json`` funding metadata with ``.github/FUNDING.yml`` -7. ``wiki --init`` - initializes wiki as submodule +7. ``wiki --target=.dev-tools/wiki-generated`` - generates local wiki Markdown 8. ``gitignore`` - merges .gitignore files 9. ``gitattributes`` - manages export-ignore rules 10. ``skills`` - synchronizes packaged skills @@ -114,7 +114,12 @@ Behavior ``.gitattributes``, ``LICENSE``, and Git hooks. - ``--interactive`` prompts before replacing drifted managed files when the command is running in an interactive terminal. -- Creates ``.github/wiki`` as a git submodule when missing. +- Generates local API Markdown in ``.dev-tools/wiki-generated`` without + creating or updating a wiki Git submodule. +- Existing workflow files are preserved unless ``--overwrite`` is requested. + To adopt direct wiki publication, migrate the existing ``wiki.yml`` and + ``wiki-maintenance.yml`` wrappers explicitly or sync with ``--overwrite``. + The packaged maintenance wrapper is manual-only compatibility guidance. - Calls other commands in sequence. - Runs ``skills`` and ``agents`` in normal mode so consumer repositories receive both packaged procedural skills and packaged role prompts. diff --git a/docs/commands/wiki.rst b/docs/commands/wiki.rst index f78defe30c..609088eacc 100644 --- a/docs/commands/wiki.rst +++ b/docs/commands/wiki.rst @@ -37,7 +37,8 @@ Options Force phpDocumentor caching off for this run. ``--init`` - Initialize the configured wiki target as a Git submodule. + Legacy opt-in: initialize the configured wiki target as a Git submodule. + Normal ``dev-tools:sync`` and the direct wiki workflow do not use this option. ``--json`` Emit a structured machine-readable payload instead of the normal terminal @@ -59,9 +60,9 @@ Generate to custom directory: .. code-block:: bash - composer wiki --target=wiki + composer dev-tools wiki -- --target=.dev-tools/wiki-generated -Initialize wiki as submodule: +Initialize a legacy wiki submodule explicitly: .. code-block:: bash @@ -100,3 +101,6 @@ Behavior directory. The option only affects phpDocumentor when caching is enabled. - Uses the Markdown template from ``vendor/saggre/phpdocumentor-markdown/themes/markdown``. - The ``--init`` option creates the wiki as a Git submodule pointing to the repository wiki. +- Normal ``dev-tools:sync`` uses ``--target=.dev-tools/wiki-generated`` to + generate local Markdown. The direct wiki workflow publishes its generated + artifact to the separate GitHub Wiki repository without a parent gitlink. diff --git a/docs/internals/architecture.rst b/docs/internals/architecture.rst index 666be893c4..3e0ff1bed3 100644 --- a/docs/internals/architecture.rst +++ b/docs/internals/architecture.rst @@ -34,8 +34,9 @@ Consumer Synchronization Lifecycle ``composer.json`` scripts, funding metadata, workflow stubs, ``.editorconfig``, ``dependabot.yml``, ``.gitignore``, ``.gitattributes``, the project license, and packaged Git hooks. -6. In normal mode, ``dev-tools:sync`` also runs ``wiki --init``, - ``skills``, and ``agents`` to initialize the wiki submodule and +6. In normal mode, ``dev-tools:sync`` also runs + ``wiki --target=.dev-tools/wiki-generated``, ``skills``, and ``agents`` + to generate local API Markdown without a wiki submodule and synchronize packaged links into ``.agents/skills`` and ``.agents/agents``. 7. In ``--dry-run``, ``--check``, and ``--interactive`` modes, ``wiki``, diff --git a/docs/usage/github-actions.rst b/docs/usage/github-actions.rst index 03acf34c77..49258af597 100644 --- a/docs/usage/github-actions.rst +++ b/docs/usage/github-actions.rst @@ -59,8 +59,8 @@ The packaged wrappers currently include: * ``review.yml`` * ``changelog.yml`` * ``auto-resolve-conflicts.yml`` -* ``wiki.yml`` for pull-request wiki previews -* ``wiki-maintenance.yml`` for merged-publication and cleanup work +* ``wiki.yml`` for read-only pull-request generation and direct publication from ``main`` +* ``wiki-maintenance.yml`` as manual-only migration guidance for legacy wrappers * ``auto-assign.yml`` * ``label-sync.yml`` @@ -206,41 +206,42 @@ The ``reports.yml`` workflow is responsible for generating technical documentati Fast Forward Wiki ----------------- -Wiki automation is split into two reusable workflows and two consumer -wrappers: - -* ``wiki.yml`` calls the reusable ``wiki-preview.yml`` workflow and is - responsible only for pull-request preview updates. -* ``wiki-maintenance.yml`` calls the reusable - ``wiki-maintenance.yml`` workflow and is responsible for merged - publication, closed-preview deletion, and scheduled cleanup. - -**Behavior:** -* **Submodule Management**: Both wiki workflows work against the - ``.github/wiki`` submodule that points to the actual GitHub Wiki - repository. -* **Pull Request Preview**: ``wiki.yml`` updates a dedicated preview branch - in the wiki repository named ``pr-{number}``. -* **Preview Generation**: The preview workflow resolves the PHP version, - installs dependencies, exposes the shared ``dev-tools`` runtime, runs - ``dev-tools wiki -- --target=.github/wiki``, - commits the generated Markdown into the wiki submodule, and then updates - the parent repository's submodule pointer when needed. -* **Preview Summary**: The preview workflow appends the preview branch name - and whether the parent repository submodule pointer changed. -* **Merged Publication**: ``wiki-maintenance.yml`` promotes the matching - ``pr-{number}`` preview branch to ``master`` after a pull request is merged - into ``main`` and validates the resulting remote SHA. -* **Cleanup**: ``wiki-maintenance.yml`` deletes preview branches for closed - pull requests and also performs scheduled cleanup for stale - ``pr-{number}`` branches. -* **Maintenance Summaries**: Publish and cleanup runs append the affected - branch names or cleanup counts to the run summary. - -.. note:: - See :doc:`../configuration/repository-setup` for mandatory initial setup required for the Wiki workflow to function. - See :doc:`../advanced/branch-protection-and-bot-commits` for branch - protection, bot commit, and submodule pointer conflict guidance. +The active ``wiki.yml`` wrapper calls ``wiki-direct.yml``. The workflow follows +the container repository's direct-publication model: generate first with read +permissions, then publish the generated artifact in a separate job. + +* **Pull requests:** generate API Markdown and upload an artifact without Wiki + write credentials. There are no preview-branch or parent-pointer commits. +* **Main publication:** only ``main`` publishes. The publishing job downloads + the artifact and updates a separate checkout of the GitHub Wiki; it does not + check out or execute the project's source code. +* **Page ownership:** ``Home.md`` is generated and replaced during publication. + Generated ``classes/`` and ``functions/`` directories + are replaced during publication so removed APIs do not leave stale pages. + Maintain hand-written pages outside these generated directories and Home page. +* **Generation sources:** shared helpers and the Markdown renderer use the + workflow's selected source revisions. DevTools generates its own API using + the checked-out ``bin/dev-tools``; consumers use their installed runtime. +* **Local sync:** ``dev-tools:sync`` generates Markdown in + ``.dev-tools/wiki-generated`` and does not initialize a Git submodule. + Explicit ``wiki --init`` remains available for legacy local workflows. + +Migration from the pointer-based workflows requires updating the consumer's +``wiki.yml`` and removing its automatic maintenance triggers. The packaged +``wiki-maintenance.yml`` is now a manual-only compatibility stub. Normal sync +preserves existing files: replace the wrappers explicitly or review +``composer dev-tools:sync --overwrite``. Sync does not delete files missing +from its packaged source directory. + +Remove only the ``.github/wiki`` gitlink and its matching ``.gitmodules`` +stanza when migrating; preserve other submodules and the separate GitHub Wiki +repository. Existing Wiki content is not deleted by removing the parent +pointer. Initialize the Wiki in GitHub before enabling publication. + +Legacy reusable ``wiki-preview.yml`` and ``wiki-maintenance.yml`` implementations +remain available to consumers that have not migrated. Their branch and pointer +behavior is documented in :doc:`../advanced/branch-protection-and-bot-commits`; +new wrappers use direct publication. Fast Forward Tests ------------------ @@ -347,9 +348,10 @@ the conflicted file list is limited to: * ``.github/wiki``; * ``CHANGELOG.md``. -For ``.github/wiki`` conflicts, the workflow keeps the pull request side of the -submodule pointer because that pointer references the preview wiki branch that -belongs to the pull request. For ``CHANGELOG.md`` conflicts, it treats the base +For legacy ``.github/wiki`` conflicts, the workflow keeps the pull request side +of the submodule pointer because that pointer references the preview wiki branch +that belongs to the pull request. Direct-publication repositories have no such +pointer. For ``CHANGELOG.md`` conflicts, it treats the base branch changelog as authoritative and merges branch-only ``Unreleased`` entries back into the current top-level ``Unreleased`` section. That keeps entries in the right place even when a release was promoted while the pull request was diff --git a/resources/github-actions/wiki-maintenance.yml b/resources/github-actions/wiki-maintenance.yml index f8f15d8c32..810133c577 100644 --- a/resources/github-actions/wiki-maintenance.yml +++ b/resources/github-actions/wiki-maintenance.yml @@ -1,26 +1,12 @@ -name: "Fast Forward Wiki Maintenance" +name: Legacy Wiki Maintenance on: - pull_request_target: - types: [closed] - schedule: - - cron: '17 3 * * *' workflow_dispatch: -permissions: - contents: write - pull-requests: read - -concurrency: - group: fast-forward-wiki-maintenance-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true +permissions: {} jobs: - maintenance: - permissions: - contents: write - pull-requests: read - # This wrapper handles merged publication to the wiki master branch plus - # preview-branch cleanup. Pull-request preview generation lives in wiki.yml. - uses: php-fast-forward/dev-tools/.github/workflows/wiki-maintenance.yml@main - secrets: inherit + migration: + runs-on: ubuntu-latest + steps: + - run: echo 'Wiki publication now runs through wiki.yml without a submodule.' diff --git a/resources/github-actions/wiki.yml b/resources/github-actions/wiki.yml index cdf27268ff..0a35d8ac48 100644 --- a/resources/github-actions/wiki.yml +++ b/resources/github-actions/wiki.yml @@ -1,25 +1,14 @@ -name: "Fast Forward Wiki Update" +name: Fast Forward Wiki Update on: + push: + branches: [main] pull_request: - types: [opened, synchronize, reopened] + workflow_dispatch: permissions: - actions: write - contents: write - pull-requests: read - -concurrency: - group: fast-forward-wiki-preview-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + contents: write # Ceiling for the isolated publisher; generation remains read-only. jobs: - preview: - permissions: - actions: write - contents: write - pull-requests: read - # Pull-request wiki previews live here. Publication and preview cleanup are - # handled by the separate wiki-maintenance wrapper. - uses: php-fast-forward/dev-tools/.github/workflows/wiki-preview.yml@main - secrets: inherit + wiki: + uses: php-fast-forward/dev-tools/.github/workflows/wiki-direct.yml@main diff --git a/src/Console/Command/SyncCommand.php b/src/Console/Command/SyncCommand.php index 4f4ae847a7..ce4bb19205 100644 --- a/src/Console/Command/SyncCommand.php +++ b/src/Console/Command/SyncCommand.php @@ -164,7 +164,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int logLevel: LogLevel::WARNING, ); } else { - $this->queueDevToolsCommand(['wiki', '--init'], true, $jsonOutput, $prettyJsonOutput); + $this->queueDevToolsCommand( + ['wiki', '--target=.dev-tools/wiki-generated'], + true, + $jsonOutput, + $prettyJsonOutput + ); $this->queueDevToolsCommand(['skills'], true, $jsonOutput, $prettyJsonOutput); $this->queueDevToolsCommand(['agents'], true, $jsonOutput, $prettyJsonOutput); } diff --git a/tests/Console/Command/SyncCommandTest.php b/tests/Console/Command/SyncCommandTest.php index 096248b947..03ecd3e829 100644 --- a/tests/Console/Command/SyncCommandTest.php +++ b/tests/Console/Command/SyncCommandTest.php @@ -92,12 +92,15 @@ protected function setUp(): void #[Test] public function executeWillQueueDedicatedSynchronizationCommands(): void { + $detachedCommandLines = []; $this->processQueue->add(Argument::type(Process::class), false, false, Argument::cetera())->shouldBeCalledTimes( 2 ); - $this->processQueue->add(Argument::type(Process::class), false, true, Argument::cetera())->shouldBeCalledTimes( - 11 - ); + $this->processQueue->add(Argument::type(Process::class), false, true, Argument::cetera()) + ->will(static function (array $arguments) use (&$detachedCommandLines): void { + $detachedCommandLines[] = $arguments[0]->getCommandLine(); + }) + ->shouldBeCalledTimes(11); $this->processQueue->run($this->output->reveal()) ->willReturn(SyncCommand::SUCCESS) ->shouldBeCalledOnce(); @@ -114,6 +117,13 @@ public function executeWillQueueDedicatedSynchronizationCommands(): void )->shouldBeCalled(); self::assertSame(SyncCommand::SUCCESS, $this->executeCommand()); + $wikiCommandLines = array_values(array_filter( + $detachedCommandLines, + static fn(string $commandLine): bool => str_contains($commandLine, "'wiki'"), + )); + self::assertCount(1, $wikiCommandLines); + self::assertStringContainsString("'--target=.dev-tools/wiki-generated'", $wikiCommandLines[0]); + self::assertStringNotContainsString('--init', $wikiCommandLines[0]); } /** From c44339acd9b09b1a7f2249cceb8928e5e93cf42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Say=C3=A3o=20Lobato=20Abreu?= Date: Wed, 14 Oct 2026 16:09:49 -0300 Subject: [PATCH 2/3] fix(wiki): preserve consumer dependencies and legacy releases --- .github/workflows/changelog.yml | 12 ++++++- .../workflows/retry-transient-failures.yml | 1 + .github/workflows/wiki-direct.yml | 32 +++++++++--------- docs/getting-started/installation.rst | 18 ++++++++-- docs/usage/github-actions.rst | 8 +++-- docs/usage/syncing-consumer-projects.rst | 33 ++++++++++++------- 6 files changed, 70 insertions(+), 34 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 0644c1ca66..95c1292deb 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -274,8 +274,18 @@ jobs: safe-directories: | ${{ github.workspace }}/.github/wiki - - name: Refresh wiki preview pointer for release pull request + - name: Detect legacy Wiki gitlink if: ${{ steps.create_pr.outputs.pull-request-number != '' }} + id: legacy_wiki + run: | + if git ls-files --stage -- .github/wiki | grep -q '^160000 '; then + echo 'present=true' >> "$GITHUB_OUTPUT" + else + echo 'present=false' >> "$GITHUB_OUTPUT" + fi + + - name: Refresh wiki preview pointer for release pull request + if: ${{ steps.create_pr.outputs.pull-request-number != '' && steps.legacy_wiki.outputs.present == 'true' }} id: refresh_release_preview uses: ./.dev-tools-actions/.github/actions/wiki/refresh-preview-pointer with: diff --git a/.github/workflows/retry-transient-failures.yml b/.github/workflows/retry-transient-failures.yml index c298ce068b..07e6c2ea55 100644 --- a/.github/workflows/retry-transient-failures.yml +++ b/.github/workflows/retry-transient-failures.yml @@ -13,6 +13,7 @@ on: - Maintain Wiki Publication - Update Wiki Preview - Update Wiki + - Fast Forward Wiki Update types: - completed diff --git a/.github/workflows/wiki-direct.yml b/.github/workflows/wiki-direct.yml index 8916ff09ef..58196d2ac5 100644 --- a/.github/workflows/wiki-direct.yml +++ b/.github/workflows/wiki-direct.yml @@ -24,33 +24,31 @@ jobs: - name: Resolve PHP version id: php uses: ./.dev-tools-actions/.github/actions/php/resolve-version - - name: Select the same pinned renderer - run: | - php <<'PHP' - 'path', - 'url' => '.dev-tools-actions', - 'options' => ['symlink' => false, 'versions' => ['fast-forward/dev-tools' => 'dev-main']], - ]; - } - $data['config']['allow-plugins']['fast-forward/dev-tools'] = false; - file_put_contents($file, json_encode($data, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT)); - PHP - name: Setup PHP and dependencies uses: ./.dev-tools-actions/.github/actions/php/setup-composer with: php-version: ${{ steps.php.outputs.php-version }} root-version: dev-main + install-options: --prefer-dist --no-progress --no-interaction --no-plugins --no-scripts + - name: Install the pinned Markdown renderer + working-directory: .dev-tools-actions + env: + COMPOSER_ROOT_VERSION: dev-main + run: composer install --prefer-dist --no-progress --no-interaction --no-scripts - name: Generate API pages run: | + mkdir -p vendor/bin vendor/saggre/phpdocumentor-markdown/themes/markdown + cp .dev-tools-actions/vendor/bin/phpdoc vendor/bin/phpdoc + chmod +x vendor/bin/phpdoc + rsync -a --delete .dev-tools-actions/vendor/saggre/phpdocumentor-markdown/themes/markdown/ vendor/saggre/phpdocumentor-markdown/themes/markdown/ if [ "$GITHUB_REPOSITORY" = php-fast-forward/dev-tools ]; then ./bin/dev-tools wiki --target=.dev-tools/wiki-generated --cache-dir="${RUNNER_TEMP}/wiki-phpdoc-cache" else - dev-tools wiki --target=.dev-tools/wiki-generated --cache-dir="${RUNNER_TEMP}/wiki-phpdoc-cache" + export DEV_TOOLS_BINARY="$GITHUB_WORKSPACE/.dev-tools-actions/bin/dev-tools" + export DEV_TOOLS_AUTOLOAD="$GITHUB_WORKSPACE/.dev-tools-actions/vendor/autoload.php" + export DEV_TOOLS_AUTO_RESOLVE_AUTOLOAD="$DEV_TOOLS_AUTOLOAD" + export DEV_TOOLS_RUNTIME_SOURCE=workflow + ./.dev-tools-actions/bin/dev-tools wiki --target=.dev-tools/wiki-generated --cache-dir="${RUNNER_TEMP}/wiki-phpdoc-cache" fi test -s .dev-tools/wiki-generated/Home.md - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 diff --git a/docs/getting-started/installation.rst b/docs/getting-started/installation.rst index 03c42f6de7..ee3fd12a15 100644 --- a/docs/getting-started/installation.rst +++ b/docs/getting-started/installation.rst @@ -10,7 +10,7 @@ Requirements - PHP 8.3 or newer. - Composer 2. - A project with PSR-4 autoload definitions in ``composer.json``. -- Git, if you want ``dev-tools:sync`` to create the repository wiki submodule. +- Git, for repository metadata and workflow synchronization. Install with Composer --------------------- @@ -40,14 +40,26 @@ following steps: hooks that prefer a project-local ``grumphp.yml`` override and otherwise use a project-relative reference to the active packaged DevTools ``grumphp.yml`` path. -6. If ``.github/wiki`` is missing, ``dev-tools:sync`` adds it as a Git - submodule that points to the repository wiki. +6. In normal mode, ``dev-tools:sync`` generates local Markdown documentation + in ``.dev-tools/wiki-generated`` without initializing a Wiki submodule. 7. ``dev-tools:sync`` runs ``gitignore`` to merge canonical ignore rules into the consumer project. 8. ``dev-tools:sync`` runs ``skills`` and ``agents`` to create or repair packaged links inside ``.agents/skills`` and ``.agents/agents`` when sync runs in normal mode rather than preview/check mode. +Wiki publication is separate from local synchronization. The synchronized +``wiki.yml`` wrapper calls ``wiki-direct.yml`` to generate documentation with +read-only permissions on pull requests and publish directly to the separate +Wiki repository from ``main``. Its isolated, pinned DevTools checkout provides +the renderer without changing the consumer's ``composer.json``, +``composer.lock``, or plugin allowlist. + +The synchronized ``wiki-maintenance.yml`` is a manual-only migration notice. +Existing callers of the legacy reusable preview and maintenance workflows +remain supported until they migrate. The explicit ``wiki --init`` option also +remains available for legacy submodule users; normal sync does not use it. + First commands to try --------------------- diff --git a/docs/usage/github-actions.rst b/docs/usage/github-actions.rst index 49258af597..c3057defe7 100644 --- a/docs/usage/github-actions.rst +++ b/docs/usage/github-actions.rst @@ -220,8 +220,12 @@ permissions, then publish the generated artifact in a separate job. are replaced during publication so removed APIs do not leave stale pages. Maintain hand-written pages outside these generated directories and Home page. * **Generation sources:** shared helpers and the Markdown renderer use the - workflow's selected source revisions. DevTools generates its own API using - the checked-out ``bin/dev-tools``; consumers use their installed runtime. + workflow's selected source revision in a separate Composer installation. + Consumer dependencies are installed without plugins or scripts; their + manifest, lock file, version constraints and plugin allowlist are preserved. + The signed phpDocumentor binary and Markdown theme come from the isolated + renderer. DevTools generates its own API using the checked-out + ``bin/dev-tools``; consumers use the explicit pinned renderer binary. * **Local sync:** ``dev-tools:sync`` generates Markdown in ``.dev-tools/wiki-generated`` and does not initialize a Git submodule. Explicit ``wiki --init`` remains available for legacy local workflows. diff --git a/docs/usage/syncing-consumer-projects.rst b/docs/usage/syncing-consumer-projects.rst index 09196cd7e0..1f4d239024 100644 --- a/docs/usage/syncing-consumer-projects.rst +++ b/docs/usage/syncing-consumer-projects.rst @@ -48,9 +48,10 @@ What the Command Changes - Creates or repairs symlinks to packaged project agents. - Creates missing links, repairs broken symlinks, and preserves existing non-symlink directories. - * - ``.github/wiki`` - - Adds a Git submodule derived from ``git remote origin``. - - Only when missing. + * - ``.dev-tools/wiki-generated`` + - Generates local Markdown API documentation without creating a Git + submodule. + - Generated in normal mode; skipped in preview/check modes. * - ``.git/hooks/*`` - Copies packaged hooks that prefer a local ``grumphp.yml`` override and otherwise use a project-relative reference to the active packaged @@ -71,8 +72,8 @@ What It Needs ------------- - a writable ``composer.json`` in the consumer project; -- a configured ``git remote origin`` if the wiki submodule must be created; - permission to create local ``.github/`` files; +- permission to write local ``.dev-tools/wiki-generated`` documentation; - permission to create local ``.agents/skills`` and ``.agents/agents`` entries. @@ -84,16 +85,26 @@ full implementation. The actual reusable workflows live in the upstream ``php-fast-forward/dev-tools`` repository. When those reusable workflows need local action implementations, they explicitly check out the upstream ``php-fast-forward/dev-tools`` repository into a dedicated -``.dev-tools-actions`` path in the run workspace first, using sparse checkout -for ``.github/actions`` only, so the consumer repository does not need to -mirror ``.github/actions`` locally. +``.dev-tools-actions`` path in the run workspace first, so the consumer +repository does not need to mirror ``.github/actions`` locally. Workflows that +need only shared actions can use sparse checkout. The direct Wiki workflow +uses a full checkout pinned to a commit, installs the renderer there, and runs +it against the consumer project without changing its ``composer.json``, +``composer.lock``, or plugin allowlist. That matters most for these cases: -* ``.github/workflows/wiki.yml`` now handles only pull-request wiki previews. -* ``.github/workflows/wiki-maintenance.yml`` handles publication to the wiki - ``master`` branch after merge, closed-preview deletion, and scheduled - cleanup. +* ``.github/workflows/wiki.yml`` calls ``wiki-direct.yml`` for read-only + generation on pull requests and direct publication from ``main`` to the + separate Wiki repository. Only ``Home.md``, ``classes/``, and ``functions/`` + are generated surfaces; manually maintained pages outside them are + preserved. +* The packaged ``.github/workflows/wiki-maintenance.yml`` is a manual-only + migration notice. Legacy reusable ``wiki-preview.yml`` and + ``wiki-maintenance.yml`` remain available for unmigrated callers. +* Normal sync generates ``.dev-tools/wiki-generated`` without ``--init``. + The explicit ``wiki --init`` option remains available for legacy submodule + users. * ``.github/workflows/auto-assign.yml`` and ``.github/workflows/changelog.yml`` accept a ``project`` input in the wrapper and also support the ``PROJECT`` repository variable. From fcbea51467213125396c95c80bfa09d99c3b6afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Say=C3=A3o=20Lobato=20Abreu?= Date: Wed, 14 Oct 2026 16:24:42 -0300 Subject: [PATCH 3/3] fix(wiki): retain no-API skips and align remaining guides --- .github/workflows/wiki-direct.yml | 12 ++++- .../branch-protection-and-bot-commits.rst | 46 +++++++++++------ docs/advanced/consumer-automation.rst | 49 +++++++++---------- docs/configuration/repository-setup.rst | 14 ++++-- docs/configuration/tooling-defaults.rst | 6 ++- docs/faq.rst | 8 ++- docs/links/dependencies.rst | 3 +- docs/running/specialized-commands.rst | 7 ++- docs/troubleshooting.rst | 11 ++++- docs/usage/common-workflows.rst | 3 +- docs/usage/documentation-workflows.rst | 7 ++- .../usage/migrating-consumer-repositories.rst | 24 ++++++--- 12 files changed, 129 insertions(+), 61 deletions(-) diff --git a/.github/workflows/wiki-direct.yml b/.github/workflows/wiki-direct.yml index 58196d2ac5..d4e9887920 100644 --- a/.github/workflows/wiki-direct.yml +++ b/.github/workflows/wiki-direct.yml @@ -10,6 +10,8 @@ jobs: generate: runs-on: ubuntu-latest timeout-minutes: 20 + outputs: + generated: ${{ steps.generate.outputs.generated }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: @@ -36,7 +38,14 @@ jobs: COMPOSER_ROOT_VERSION: dev-main run: composer install --prefer-dist --no-progress --no-interaction --no-scripts - name: Generate API pages + id: generate run: | + has_api=$(php -r 'require ".dev-tools-actions/vendor/autoload.php"; echo FastForward\DevTools\Container\ContainerFactory::get(FastForward\DevTools\Project\ProjectCapabilitiesResolverInterface::class)->resolve()->canGenerateApiDocumentation() ? "true" : "false";') + echo "generated=${has_api}" >> "$GITHUB_OUTPUT" + if [ "$has_api" = false ]; then + echo 'No autoloaded PHP API directories; skip Wiki generation and publication.' + exit 0 + fi mkdir -p vendor/bin vendor/saggre/phpdocumentor-markdown/themes/markdown cp .dev-tools-actions/vendor/bin/phpdoc vendor/bin/phpdoc chmod +x vendor/bin/phpdoc @@ -52,13 +61,14 @@ jobs: fi test -s .dev-tools/wiki-generated/Home.md - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + if: steps.generate.outputs.generated == 'true' with: name: wiki path: .dev-tools/wiki-generated if-no-files-found: error publish: - if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' && needs.generate.outputs.generated == 'true' needs: generate runs-on: ubuntu-latest timeout-minutes: 5 diff --git a/docs/advanced/branch-protection-and-bot-commits.rst b/docs/advanced/branch-protection-and-bot-commits.rst index d54dbe0151..90ded68775 100644 --- a/docs/advanced/branch-protection-and-bot-commits.rst +++ b/docs/advanced/branch-protection-and-bot-commits.rst @@ -9,22 +9,30 @@ updates. The model has two publishing lanes: -- pull requests publish isolated previews; +- pull requests provide report previews and read-only Wiki artifacts; - merges into ``main`` publish the final wiki and reports. -For wiki automation, those lanes are now split across separate reusable -workflows: +The active ``wiki.yml`` calls ``wiki-direct.yml``. Its generation job has +read-only permissions on pull requests; after merge, a separate job publishes +from ``main`` to the Wiki repository. It does not create preview branches, +commit repository pointers, or require Wiki-related bot commits on PR branches. + +Legacy consumers that have not migrated still use separate reusable workflows: - ``.github/workflows/wiki-preview.yml`` handles preview generation for pull - requests and is triggered through ``.github/workflows/wiki.yml``; + requests through a legacy consumer wrapper; - ``.github/workflows/wiki-maintenance.yml`` handles post-merge promotion, closed-pull-request cleanup, and scheduled orphan cleanup and is triggered - through ``.github/workflows/wiki-maintenance-entry.yml``. + through a legacy consumer maintenance wrapper. The producer maintenance entry + and current packaged consumer maintenance stub are manual-only notices. Wiki Preview Lifecycle ---------------------- -The wiki workflow writes generated Markdown to the GitHub wiki repository, but +This section describes legacy preview/submodule consumers only. The direct +workflow uses a generated artifact on pull requests instead. + +The legacy wiki workflow writes generated Markdown to the GitHub wiki repository, but it does not publish pull request content directly to the wiki ``master`` branch. Instead, each pull request receives a dedicated wiki branch. @@ -92,6 +100,9 @@ respect those rules: - final reports publication runs from the already-accepted ``main`` revision; - preview branches such as ``pr-123`` are temporary review targets. +The pointer and preview-branch guidance below applies only to legacy Wiki +consumers. Direct Wiki publication does not push to pull request branches. + If a repository restricts bot pushes to pull request branches, maintainers should either allow the workflow token to update PR branches or require authors to refresh generated pointers manually. The preferred path is to allow bot @@ -220,7 +231,12 @@ comment. Scheduled preview cleanup uses ``pull-requests: read`` so it can distinguish open pull requests from closed or merged ones before deleting ``previews/pr-`` directories. -``wiki.yml`` is now preview-only, so its called workflow keeps +The active ``wiki.yml`` caller permits ``contents: write`` so the separate +``wiki-direct.yml`` publication job can publish from ``main``. Its generation +job explicitly keeps ``contents: read`` and checkouts do not persist +credentials. Pull requests never run the publication job. + +The legacy ``wiki-preview.yml`` keeps ``contents: write`` for wiki preview commits and parent-repository submodule pointer updates, ``actions: write`` to dispatch ``tests.yml`` after bot-authored pointer commits, and ``pull-requests: read`` to inspect pull request metadata @@ -231,7 +247,7 @@ predictable conflict-resolution commits, ``pull-requests: write`` so it can inspect pull request state through GitHub tooling, and ``actions: write`` so it can dispatch ``tests.yml`` after it pushes a bot-authored resolution commit. -``wiki-maintenance-entry.yml`` and ``wiki-maintenance.yml`` keep +The legacy reusable ``wiki-maintenance.yml`` keeps ``contents: write`` for wiki publication and cleanup tasks, and ``pull-requests: read`` on jobs that need to distinguish merged, closed, and open pull requests before publishing or deleting preview branches. @@ -265,6 +281,9 @@ updating a release pull request. Resolving ``.github/wiki`` Pointer Conflicts -------------------------------------------- +This section applies only to legacy submodule consumers. Direct Wiki publication +does not create repository pointers. + Submodule pointer conflicts happen when ``main`` and the pull request point to different generated wiki commits. The predictable-conflict workflow can resolve this automatically when the conflict scope is limited to ``.github/wiki`` and @@ -291,13 +310,12 @@ regenerate the wiki locally before updating the pointer. Operational Checklist --------------------- -- Keep source changes and generated pointer updates in the same pull request. -- Review PR preview links before merging documentation-heavy changes. +- Review report preview links and generated Wiki artifacts before merging + documentation-heavy changes. - Merge only through the protected ``main`` flow. -- Let the post-merge wiki job publish to ``master``. -- Treat wiki preview and wiki maintenance as separate automation concerns when - debugging workflow failures. -- Let closed pull requests and scheduled cleanup remove wiki preview branches. +- Let the direct Wiki publication job publish from ``main``. +- For legacy consumers, keep generated pointers with their source changes and + use the separate preview and maintenance workflows for publication and cleanup. - Let closed pull requests and scheduled cleanup remove report preview directories. diff --git a/docs/advanced/consumer-automation.rst b/docs/advanced/consumer-automation.rst index 06cf7488fe..46e28e0908 100644 --- a/docs/advanced/consumer-automation.rst +++ b/docs/advanced/consumer-automation.rst @@ -50,9 +50,8 @@ implementation in this repository is increasingly composed from local actions in ``GITHUB_STEP_SUMMARY`` after workflows already know their final URLs, refs, versions, or verification results. * - ``.github/actions/wiki/*`` - - Wiki-specific helpers for preparing preview branches, promoting preview - content to ``master``, validating publication, and cleaning stale - preview branches. + - Legacy Wiki helpers for preview branches, promotion, publication + validation, and cleanup, retained for unmigrated callers. * - ``.github/dependabot.yml`` - This repository's own Dependabot configuration. * - ``resources/dependabot.yml`` @@ -63,9 +62,9 @@ implementation in this repository is increasingly composed from local actions in * - ``.agents/agents/*`` - Packaged project-agent prompts linked into consumer repositories by the ``agents`` command. - * - ``.github/wiki`` - - Generated Markdown API documentation locally and wiki submodule content - in consumer repositories. + * - ``.dev-tools/wiki-generated`` + - Local Markdown API documentation generated by normal sync and the direct + Wiki workflow without a repository submodule. How GitHub Pages Publishing Works --------------------------------- @@ -81,26 +80,26 @@ How GitHub Pages Publishing Works How Wiki Publishing Works ------------------------- -Wiki automation now has two distinct entry workflows: - -- ``.github/workflows/wiki.yml`` handles pull-request preview generation by - calling ``.github/workflows/wiki-preview.yml``. -- ``.github/workflows/wiki-maintenance-entry.yml`` handles post-merge - publication, closed-pull-request cleanup, and scheduled orphan cleanup by - calling ``.github/workflows/wiki-maintenance.yml``. - -Within those reusable workflows, the lower-level branch preparation, publish -validation, and cleanup steps live under ``.github/actions/wiki/*``. +The active ``.github/workflows/wiki.yml`` calls ``wiki-direct.yml``. The +generation job uses read-only permissions; a separate publication job runs +only from ``main`` with Wiki write permissions. Consumer generation uses a +full, pinned DevTools checkout with an isolated renderer installation, +preserving the consumer's Composer manifest, lock file, and plugin allowlist. In practice: -- pull requests publish generated wiki content to branches such as ``pr-123``; -- the parent repository then commits the updated submodule pointer to the pull - request branch; -- after merge, the maintenance workflow promotes the preview content to the - wiki ``master`` branch; -- closed pull requests and the scheduled maintenance lane remove stale preview - branches. +- pull requests generate a reviewable artifact without publishing Wiki content + or committing submodule pointers; +- after merge, ``main`` generates and publishes directly to the separate Wiki + repository; +- publication replaces generated ``Home.md``, ``classes/``, and ``functions/`` + content while preserving manually maintained pages outside those surfaces; +- normal local sync writes ``.dev-tools/wiki-generated`` without ``--init``. + +The producer's ``wiki-maintenance-entry.yml`` and packaged consumer +``wiki-maintenance.yml`` are manual-only migration notices. Legacy reusable +``wiki-preview.yml`` and ``wiki-maintenance.yml`` still support unmigrated +callers using the preview-branch and submodule model. How Changelog and Project Automation Fit In ------------------------------------------- @@ -115,7 +114,7 @@ How Changelog and Project Automation Fit In ``.github/actions/review/*`` and posts a deterministic brief that points maintainers to the packaged ``review-guardian`` agent and ``pull-request-review`` skill. -- ``tests.yml``, ``reports.yml``, wiki preview and maintenance flows, and +- ``tests.yml``, ``reports.yml``, legacy wiki preview and maintenance flows, and ``changelog.yml`` now delegate final run summaries to ``.github/actions/summary/*`` after their final-state information is known. - Project-board automation is no longer just an inline workflow concern; it is @@ -123,7 +122,7 @@ How Changelog and Project Automation Fit In release automation. See :doc:`branch-protection-and-bot-commits` for the branch protection model, -bot commit behavior, and ``.github/wiki`` conflict resolution steps. +bot commit behavior, and legacy ``.github/wiki`` conflict resolution steps. Producer Impact --------------- diff --git a/docs/configuration/repository-setup.rst b/docs/configuration/repository-setup.rst index 1e9bbfb715..db3d4db17a 100644 --- a/docs/configuration/repository-setup.rst +++ b/docs/configuration/repository-setup.rst @@ -21,11 +21,17 @@ FastForward DevTools automatically generates and deploys reports, test coverage, GitHub Wiki ----------- -The wiki synchronization feature allows you to maintain documentation in Markdown within your repository and have it automatically published to the GitHub Wiki. +Normal sync generates local API Markdown in ``.dev-tools/wiki-generated`` +without a submodule. The direct Wiki workflow generates a read-only artifact on +pull requests and publishes directly from ``main`` to the separate GitHub Wiki +repository. .. important:: **Initial Manual Step Required** - GitHub does not create the underlying wiki repository until at least one page is created via the web interface. You **MUST** create an initial ``Home.md`` page manually before using ``dev-tools wiki --init`` or any automated sync features. + GitHub does not create the underlying Wiki repository until at least one + page is created via the web interface. Create an initial ``Home`` page before + automated publication or legacy ``wiki --init``. Local Markdown generation + does not require this remote initialization. 1. Navigate to your repository on GitHub. 2. Click the **Wiki** tab. @@ -33,7 +39,9 @@ The wiki synchronization feature allows you to maintain documentation in Markdow 4. Ensure the title is ``Home`` and add some initial content. 5. Click **Save Page**. -Once this is done, the wiki can be cloned as a submodule and synchronized by the DevTools commands. +Once this is done, the direct workflow can clone the separate Wiki repository +for publication. Only legacy users who explicitly choose ``wiki --init`` need +a local submodule. Workflow Permissions -------------------- diff --git a/docs/configuration/tooling-defaults.rst b/docs/configuration/tooling-defaults.rst index 03ca333589..69ade03233 100644 --- a/docs/configuration/tooling-defaults.rst +++ b/docs/configuration/tooling-defaults.rst @@ -46,8 +46,10 @@ Generated and Cache Directories coverage data. - ``.dev-tools/metrics/`` contains PhpMetrics HTML output plus the generated ``report.json`` and ``report-summary.json`` artifacts. -- ``.github/wiki/`` contains generated Markdown API documentation and, in - consumer repositories, the wiki submodule. +- ``.dev-tools/wiki-generated/`` contains local Markdown API documentation + from normal sync and the direct Wiki workflow. +- ``.github/wiki/`` remains the standalone ``wiki`` command's default target; + legacy consumers may also use it as an explicitly initialized Wiki submodule. - ``.agents/skills/`` contains symlinked packaged skills or consumer-owned directories kept in place by the ``skills`` command. - ``.agents/agents/`` contains symlinked packaged project agents or diff --git a/docs/faq.rst b/docs/faq.rst index 56752e5b2e..901ef1454a 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -84,8 +84,12 @@ only ``AddMissingMethodPhpDocRector`` and ``RemoveEmptyDocBlockRector``. What happens if ``.github/wiki`` already exists? ------------------------------------------------ -``dev-tools:sync`` leaves it alone. The wiki submodule is only created when the -directory is missing. +``dev-tools:sync`` leaves it alone and generates local API Markdown in +``.dev-tools/wiki-generated`` instead. Normal sync does not create or update a +Wiki submodule. When migrating to direct Wiki publication, remove the obsolete +gitlink and matching ``.gitmodules`` stanza explicitly, preserving the separate +Wiki repository and any other submodules. ``wiki --init`` remains available as +an explicit legacy option. What happens if ``.agents/skills/my-skill`` already exists? ----------------------------------------------------------- diff --git a/docs/links/dependencies.rst b/docs/links/dependencies.rst index 6eeea55f1f..e10b7f7b6e 100644 --- a/docs/links/dependencies.rst +++ b/docs/links/dependencies.rst @@ -105,7 +105,8 @@ Utility Packages Environment Assumptions ----------------------- -- Git is required for wiki submodule creation. +- Git is used for direct Wiki publication and explicit legacy submodule + initialization; normal sync generates local Markdown without a submodule. - ``pcov`` is used in the reusable GitHub Actions workflows for coverage. - ``pcntl`` improves asynchronous notification delivery on platforms that support it. diff --git a/docs/running/specialized-commands.rst b/docs/running/specialized-commands.rst index 4bb360e565..371ba5b95c 100644 --- a/docs/running/specialized-commands.rst +++ b/docs/running/specialized-commands.rst @@ -252,6 +252,9 @@ Builds Markdown API pages for a GitHub wiki. Important details: - the default output directory is ``.github/wiki``; +- normal ``dev-tools:sync`` and the direct Wiki workflow explicitly use + ``.dev-tools/wiki-generated`` without initializing a submodule; +- ``--init`` remains an explicit legacy option for submodule users; - it uses the Markdown template from ``vendor/saggre/phpdocumentor-markdown/themes/markdown``; - cache stays enabled by default; ``--cache`` forces it on and ``--no-cache`` @@ -390,8 +393,8 @@ Important details: - it copies missing workflow stubs, ``.editorconfig``, and ``dependabot.yml``; - it calls ``codeowners`` to generate ``.github/CODEOWNERS`` from local metadata; -- it creates ``.github/wiki`` as a git submodule when the directory is - missing. +- in normal mode it generates local API Markdown in + ``.dev-tools/wiki-generated`` without creating a Git submodule; - it calls ``gitignore`` to merge the canonical .gitignore with the project's .gitignore; - it calls ``gitattributes`` to manage export-ignore rules in .gitattributes; diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst index 3b47c39afd..09836f5ce3 100644 --- a/docs/troubleshooting.rst +++ b/docs/troubleshooting.rst @@ -78,11 +78,12 @@ the DevTools package source needed for the fallback runtime. Branch Protection or Bot Commit Blocks -------------------------------------- -Scope: GitHub Actions. +Scope: GitHub Actions. Wiki preview and pointer symptoms below apply only to +legacy consumers; the direct Wiki workflow generates read-only PR artifacts. Symptoms: -- a wiki or reports preview job cannot push generated updates; +- a legacy wiki or reports preview job cannot push generated updates; - GitHub rejects a bot commit with a protected-branch error; - a pull request is mergeable locally but blocked after the preview job runs. @@ -106,6 +107,9 @@ Recovery: Scope: local and CI. +This section applies only to legacy Wiki submodule consumers. Normal sync and +direct Wiki publication do not create or update these pointers. + Symptoms: - Git reports a conflict on ``.github/wiki``; @@ -257,6 +261,9 @@ Reports or Wiki Preview Cleanup Issues Scope: GitHub Actions. +Wiki preview branches and their cleanup apply only to legacy workflows. +The direct Wiki workflow has no PR preview branches or maintenance cleanup lane. + Symptoms: - closed pull requests still show old report preview links; diff --git a/docs/usage/common-workflows.rst b/docs/usage/common-workflows.rst index cd2c7a103e..d61b0c96bc 100644 --- a/docs/usage/common-workflows.rst +++ b/docs/usage/common-workflows.rst @@ -46,7 +46,8 @@ Most day-to-day work falls into one of the flows below. packaged skills and packaged agents. * - Regenerate wiki pages - ``composer wiki`` - - Builds Markdown API pages in ``.github/wiki``. + - Builds Markdown API pages in ``.github/wiki`` by default; normal sync + explicitly uses ``.dev-tools/wiki-generated`` without a submodule. Choose the Right Entry Point ---------------------------- diff --git a/docs/usage/documentation-workflows.rst b/docs/usage/documentation-workflows.rst index 570c828674..8c4d2f5966 100644 --- a/docs/usage/documentation-workflows.rst +++ b/docs/usage/documentation-workflows.rst @@ -54,7 +54,9 @@ What Each Command Is For - ``docs`` builds the HTML documentation site. It fails early if the source guide directory does not exist. -- ``wiki`` builds Markdown API pages intended for ``.github/wiki``. +- Standalone ``wiki`` builds Markdown API pages in ``.github/wiki`` by default. + Normal sync and the direct Wiki workflow explicitly select + ``.dev-tools/wiki-generated`` without initializing a submodule. - ``reports`` runs ``docs``, ``tests --coverage``, and ``metrics`` using the selected DevTools workspace defaults. With the default workspace that means ``docs --target .dev-tools``, ``tests --coverage .dev-tools/coverage``, and @@ -72,7 +74,8 @@ Outputs to Expect ``reports`` or ``tests --coverage`` is used; - metrics data under the selected workspace ``metrics`` directory when ``reports`` or ``metrics`` is used; -- Markdown API pages under ``.github/wiki`` when ``wiki`` is used. +- Markdown API pages under ``.github/wiki`` for standalone ``wiki`` by default, + or ``.dev-tools/wiki-generated`` for normal sync and the direct Wiki workflow. Troubleshooting --------------- diff --git a/docs/usage/migrating-consumer-repositories.rst b/docs/usage/migrating-consumer-repositories.rst index 7f79fd92bc..839d5ddda8 100644 --- a/docs/usage/migrating-consumer-repositories.rst +++ b/docs/usage/migrating-consumer-repositories.rst @@ -78,9 +78,9 @@ Expected changes can include: * - ``.github/dependabot.yml`` - Adds the shared Dependabot template when missing. - Confirm update cadence and ecosystem coverage. - * - ``.github/wiki`` - - Adds the wiki submodule when missing. - - Confirm the wiki repository exists and branch protection is compatible. + * - ``.dev-tools/wiki-generated`` + - Generates local API Markdown without creating a submodule. + - Review the generated pages and direct Wiki workflow configuration. * - ``.agents/skills`` - Links packaged skills for issue, PR, tests, docs, README, and style work. - Preserve existing custom skills and non-symlink directories. @@ -110,6 +110,17 @@ repository-specific ``.gitignore`` rules, and existing Dependabot policies. Shared defaults are meant to reduce repeated maintenance, not erase local constraints. +When adopting direct Wiki publication, update an existing ``wiki.yml`` wrapper +explicitly to call ``wiki-direct.yml`` and remove automatic maintenance +triggers. Normal sync preserves existing workflow files by default. The +packaged ``wiki-maintenance.yml`` is a manual-only migration notice; legacy +reusable preview and maintenance workflows remain available for unmigrated +callers. + +Remove only the obsolete ``.github/wiki`` gitlink and its matching +``.gitmodules`` stanza, preserving other submodules and the separate GitHub +Wiki repository. Local sync does not remove an existing pointer automatically. + Branch Protection and Bot Commits --------------------------------- @@ -118,12 +129,13 @@ Fast Forward model: - pull requests receive generated previews and bot updates on the PR branch; - report previews are published under PR-specific Pages paths; -- wiki previews use branches such as ``pr-123`` before merge; +- the direct Wiki workflow generates a read-only artifact on pull requests, + without publishing a preview branch or committing a submodule pointer; - post-merge jobs publish final reports and wiki content from ``main``. If branch protection blocks bot commits to pull request branches, either adjust the repository policy to allow workflow updates on PR branches or document that -maintainers must refresh generated pointers manually before merge. +maintainers must apply those bot-managed changes manually before merge. Suggested Pull Request Rollout ------------------------------ @@ -135,7 +147,7 @@ Use one migration pull request per consumer repository: 3. review and adapt generated files; 4. run the smallest relevant local verification command; 5. open the pull request and let GitHub Actions create previews; -6. verify report and wiki preview links before merge; +6. verify report preview links and the generated Wiki artifact before merge; 7. merge through the protected ``main`` branch. After merge, confirm that the final reports and wiki pages reflect the merged