Refactor project:* commands to Action/Result pattern#284
Merged
Conversation
Extracts API logic from all project:* commands into channel-agnostic Action classes returning typed Result DTOs, matching the pattern established for issue:* commands in #278/#283. - Add GetProjectLinkAction, GetProjectKanbanLinkAction (pure, no Client) - Add GetProjectReleasesAction, GetProjectIssuesAction, GetProjectReleaseNotesAction (Client-injected) - Add ProjectLinkResult (shared), ProjectReleasesResult, ProjectIssuesResult, ProjectReleaseNotesResult - Replace exit(1) in ReleaseNotes with RuntimeException caught in execute() - Move type/core filter switch logic into GetProjectIssuesAction - Add 14 PHPUnit tests covering happy paths, not-found errors, semver fallback, and JSON serialisation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Refactors the project:* CLI commands to follow the existing Action/Result pattern used by issue:* commands, moving Drupal.org API interactions into reusable, channel-agnostic Action classes that return typed Result DTOs.
Changes:
- Introduces new
GetProject*Actionclasses undersrc/Api/Action/Project/and correspondingProject*ResultDTOs undersrc/Api/Result/Project/. - Updates
project:releases,project:release-notes,project:issues,project:link, andproject:kanbancommands to delegate to these Actions. - Adds unit tests for the new Project Actions and JSON serialization.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/src/Action/Project/GetProjectReleasesActionTest.php | Adds coverage for releases action behavior, not-found path, and JSON serialization. |
| tests/src/Action/Project/GetProjectReleaseNotesActionTest.php | Adds coverage for release-notes action behavior, semver fallback, error paths, and JSON serialization. |
| tests/src/Action/Project/GetProjectLinkActionTest.php | Adds coverage for project link action and JSON serialization. |
| tests/src/Action/Project/GetProjectKanbanLinkActionTest.php | Adds coverage for kanban link action and JSON serialization. |
| tests/src/Action/Project/GetProjectIssuesActionTest.php | Adds coverage for issues action behavior, not-found path, and JSON serialization. |
| src/Cli/Command/Project/Releases.php | Delegates release fetching to GetProjectReleasesAction. |
| src/Cli/Command/Project/ReleaseNotes.php | Delegates release-notes lookup to GetProjectReleaseNotesAction and replaces exit(1) with exception handling. |
| src/Cli/Command/Project/ProjectIssues.php | Delegates issue filtering/fetching to GetProjectIssuesAction. |
| src/Cli/Command/Project/Link.php | Uses GetProjectLinkAction to produce the URL to open. |
| src/Cli/Command/Project/Kanban.php | Uses GetProjectKanbanLinkAction to produce the URL to open. |
| src/Api/Result/Project/ProjectReleasesResult.php | Adds typed DTO + JSON shape for releases output. |
| src/Api/Result/Project/ProjectReleaseNotesResult.php | Adds typed DTO + JSON shape for release notes output. |
| src/Api/Result/Project/ProjectLinkResult.php | Adds shared DTO for link/kanban URL output. |
| src/Api/Result/Project/ProjectIssuesResult.php | Adds DTO for project issues output + JSON shape. |
| src/Api/Action/Project/GetProjectReleasesAction.php | Adds Action that resolves project and fetches releases via Client. |
| src/Api/Action/Project/GetProjectReleaseNotesAction.php | Adds Action that resolves project and fetches release notes (with semver fallback). |
| src/Api/Action/Project/GetProjectLinkAction.php | Adds pure Action that builds the drupal.org project URL. |
| src/Api/Action/Project/GetProjectKanbanLinkAction.php | Adds pure Action that builds the contribkanban URL. |
| src/Api/Action/Project/GetProjectIssuesAction.php | Adds Action that resolves project and performs release/core/type filtering + issue lookup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Restores parity with the original exit(1) message in ReleaseNotes::execute(), which read "No release found for $version." (with period). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ctions ProjectCommandBase::initialize() already fetches and validates the project, storing it in $this->projectData. The three project actions were re-fetching it internally via getProject(), causing a redundant HTTP request per command. Change GetProjectReleasesAction, GetProjectIssuesAction, and GetProjectReleaseNotesAction to accept a Project entity as their first argument instead of a machine name string. Remove the null guard from each action (the caller is responsible for a valid Project). Update the three corresponding commands to pass $this->projectData. Update tests to construct Project::fromStdClass() and pass it directly, removing getProject() mocks and the now-inapplicable testInvokeThrowsWhenProjectNotFound cases. Also fix CLAUDE.md: Client.php has only retry middleware (429/503), not cache middleware as previously stated. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Map raw stdClass issue objects through IssueNode::fromStdClass() in GetProjectIssuesAction, consistent with how ProjectReleasesResult uses Release[]. Update jsonSerialize() to emit an explicit array shape and use typed camelCase property access in the ProjectIssues command. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
project:*commands into channel-agnostic Action classes returning typed Result DTOs, matching the pattern established forissue:*commands in Refactor remaining issue:* commands to Action/Result pattern #278/Refactor issue:link, issue:branch, issue:apply to Action/Result pattern #283GetProjectLinkActionandGetProjectKanbanLinkAction(pure, no Client) sharing a singleProjectLinkResultGetProjectReleasesAction,GetProjectIssuesAction, andGetProjectReleaseNotesActionwithClientinjected via constructorProjectIssues::execute()intoGetProjectIssuesActionexit(1)inReleaseNotes::execute()withthrow new \RuntimeException()caught inexecute()ProjectCommandBaseis unchangedTest plan
vendor/bin/phpunit— 45 tests, all passing (14 new tests covering happy paths, project-not-found, semver fallback, and JSON serialisation)vendor/bin/phpstan analyse src— no errorsCloses #279
🤖 Generated with Claude Code