Skip to content

feat: migrate milestone mover + tagger to unit-tested PHP#91

Merged
skjnldsv merged 7 commits into
mainfrom
feature/php-release-tools
Jun 9, 2026
Merged

feat: migrate milestone mover + tagger to unit-tested PHP#91
skjnldsv merged 7 commits into
mainfrom
feature/php-release-tools

Conversation

@skjnldsv

@skjnldsv skjnldsv commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Migrates the logic-heavy, API-driven release scripts from bash to a unit-tested PHP package (tools/release/), and switches the live workflows to it.

What moved to PHP

was (bash) now (PHP command)
update-milestones.sh milestones:update
audit-milestones.sh milestones:audit
tag-repo.sh repo:tag
  • Transport: knplabs/github-api behind our own GitHub\GitHubApi interface. Tags are created as lightweight refs via the git-refs API (no clone/push). Issue moves now skip pull requests.
  • Layers: pure domain (Version, MilestonePlan, DueDate, RepoList, AuditExpectation, TagPolicy, ReleaseConfig) -> services (MilestoneUpdater, MilestoneAuditor, RepoTagger) -> thin Symfony Console commands.
  • Workflows: release-milestones.yml and release-tag.yml set up PHP + composer and call the commands (same inputs, same RELEASE_TOKEN). Added a dry_run input to the tagger.
  • Removed: the three bash scripts, tests/milestone-scripts/**, test-milestone-scripts.yml.

Testing

  • 55 PHPUnit tests against an in-memory FakeGitHubApi (records a journal of mutations) covering every release shape and tagger combination; each test file documents what/why in its docblock. FakeGitHubApi lives in tests/ (not shipped in src/).
  • CI runs the suite as a per-area matrix (domain, milestones-update, milestones-audit, tagger) on every push/PR, with pcov coverage uploaded to Codecov per area.
  • Validated against the real API on this branch (dry-run, no writes):
    • milestones:update v34.0.0 -> would close Nextcloud 34 across 29 repos
    • repo:tag v34.0.1 -> would tag 30 repos at resolved branch SHAs, 0 failed
    • milestones:update v34.0.0beta1 -> first-beta path creates Nextcloud 35 (N+1), idempotent where it already exists

Docs

Root README.md explains the release process and branch/milestone rules; tools/release/README.md documents the full auto-logic in human-friendly form.

Notes

  • Build/packaging scripts (assemble, package, sign, ...) stay bash by design.
  • composer.lock pins platform.php to 8.3 so CI and local resolve identically.
  • codecov/codecov-action@v5 uses a version tag; pin to a SHA if the repo requires it.

First step of migrating the logic-heavy release scripts from bash to a
unit-tested PHP package. This lands the scaffold and the pure milestone
domain only - no I/O, no workflow changes, nothing cut over yet. It sits
beside the bash and is consumed in a later step.

- tools/release: composer package (Symfony-Console-ready), PHPUnit 12, CI.
- Domain (pure, zero mocks):
  - Version       - parse a tag into major/minor/patch + prerelease/first-beta
  - MilestonePlan - current/next/upcoming names; first beta -> next major (N+1)
  - DueDate       - validate YYYY-MM-DD, convert to ISO
  - RepoList      - merge config + tag-only lists (sorted, unique)
  - AuditExpectation - expected milestone state + orphan rule
- 22 tests / 69 assertions. These encode the exact rules that caused bugs in
  the bash version (first-beta off-by-one, the two-open-patch invariant) and
  catch them with plain assertions - no fixtures or fake-gh needed.

Next: wire these behind a mockable GitHub client + Console commands
(milestones:update / milestones:audit), then retire update-milestones.sh.

Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
@skjnldsv skjnldsv added the enhancement New feature or request label Jun 9, 2026
skjnldsv added 5 commits June 9, 2026 10:15
…rkflows

Step 2 of the bash->PHP migration. The milestone mover (update-milestones.sh
+ audit-milestones.sh) and the tagger (tag-repo.sh) are reimplemented as
unit-tested PHP commands and the live workflows now call them. The bash
scripts and their fake-gh harness are removed.

tools/release additions:
- GitHub\GitHubApi interface with a knplabs-backed adapter (KnpGitHubApi) and
  an in-memory FakeGitHubApi (journal of mutations) for tests. Tags are created
  as lightweight refs via the git-refs API (no clone/push). Issue moves skip
  pull requests.
- Services: MilestoneUpdater, MilestoneAuditor, RepoTagger.
- Domain: TagPolicy (server-repo immutability), ReleaseConfig (config->major,
  latest-stable, repo list).
- Commands milestones:update, milestones:audit, repo:tag (bin/console).
- 55 PHPUnit tests covering every release shape + tagger combination via the
  fake (each test file documents what/why in its docblock).

Workflows:
- release-milestones.yml and release-tag.yml set up PHP, composer install, and
  call the console commands (same inputs, same RELEASE_TOKEN).
- test-release-tools.yml runs on all pushes/PRs (no path filter).

Removed: update-milestones.sh, audit-milestones.sh, tag-repo.sh,
tests/milestone-scripts/**, test-milestone-scripts.yml. Release auto-logic is
documented in tools/release/README.md.

Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
…with CI

Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
…verage

Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
@skjnldsv skjnldsv changed the title feat: PHP release-tools scaffold + milestone domain (step 0+1) feat: migrate milestone mover + tagger to unit-tested PHP Jun 9, 2026
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
@skjnldsv skjnldsv merged commit 3495022 into main Jun 9, 2026
7 checks passed
@skjnldsv skjnldsv deleted the feature/php-release-tools branch June 9, 2026 08:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Development

Successfully merging this pull request may close these issues.

1 participant