Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions skills/drupalorg-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ Commands that fetch data accept `--format` / `-f`:
|--------|-------------|---------|
| `text` | Human-readable plain text (default) | All commands |
| `json` | Machine-readable JSON | Most commands |
| `md` | Markdown suitable for display or copy-paste | `issue:show`, `issue:get-fork`, `mr:list`, `mr:status`, `project:issues`, `project:releases`, `project:release-notes`, `maintainer:issues` |
| `llm` | Structured XML optimised for agent consumption | `issue:show` (add `--with-comments` to include comment thread), `issue:get-fork`, `mr:list`, `mr:status`, `project:issues`, `project:releases`, `project:release-notes`, `maintainer:issues` |
| `md` | Markdown suitable for display or copy-paste | `issue:show`, `issue:get-fork`, `mr:list`, `mr:status`, `mr:files`, `mr:diff`, `project:issues`, `project:releases`, `project:release-notes`, `maintainer:issues` |
| `llm` | Structured XML optimised for agent consumption | `issue:show` (add `--with-comments` to include comment thread), `issue:get-fork`, `mr:list`, `mr:status`, `mr:files`, `mr:diff`, `project:issues`, `project:releases`, `project:release-notes`, `maintainer:issues` |

**Agents should always pass `--format=llm`** to get rich, structured output
with clearly labelled fields, contributor lists, and change records.
Expand Down Expand Up @@ -92,14 +92,14 @@ drupalorg mr:list [nid] [--state=opened] --format=llm
drupalorg mr:list project/drupal --format=llm

# Show the unified diff for a merge request
# Supports --format=text (default), json
drupalorg mr:diff <nid> <mr-iid>
drupalorg mr:diff 'project/drupal!708'
# Supports --format=text (default), json, md, llm
drupalorg mr:diff <nid> <mr-iid> --format=llm
drupalorg mr:diff 'project/drupal!708' --format=llm

# List changed files in a merge request
# Supports --format=text (default), json
drupalorg mr:files <nid> <mr-iid>
drupalorg mr:files 'project/drupal!708'
# Supports --format=text (default), json, md, llm
drupalorg mr:files <nid> <mr-iid> --format=llm
drupalorg mr:files 'project/drupal!708' --format=llm

# Show the pipeline status for a merge request
drupalorg mr:status <nid> <mr-iid> --format=llm
Expand Down
5 changes: 2 additions & 3 deletions src/Cli/Command/MergeRequest/GetDiff.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ protected function configure(): void
'format',
'f',
InputOption::VALUE_OPTIONAL,
'Output format: text, json. Defaults to text.',
'Output format: text, json, md, llm. Defaults to text.',
'text'
);
$this->configureNidAndMrIid();
Expand All @@ -32,8 +32,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$action = new GetMergeRequestDiffAction($this->client, new GitLabClient());
$result = $action($this->nid ?? '', $this->mrIid, $this->mrRef);

if ($format === 'json') {
$this->stdOut->writeln((string) json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
if ($this->writeFormatted($result, $format)) {
return 0;
}

Expand Down
5 changes: 2 additions & 3 deletions src/Cli/Command/MergeRequest/GetFiles.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ protected function configure(): void
'format',
'f',
InputOption::VALUE_OPTIONAL,
'Output format: text, json. Defaults to text.',
'Output format: text, json, md, llm. Defaults to text.',
'text'
);
$this->configureNidAndMrIid();
Expand All @@ -33,8 +33,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$action = new GetMergeRequestFilesAction($this->client, new GitLabClient());
$result = $action($this->nid ?? '', $this->mrIid, $this->mrRef);

if ($format === 'json') {
$this->stdOut->writeln((string) json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
if ($this->writeFormatted($result, $format)) {
return 0;
}

Expand Down
6 changes: 6 additions & 0 deletions src/Cli/Formatter/AbstractFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use mglaman\DrupalOrg\Result\Issue\IssueForkResult;
use mglaman\DrupalOrg\Result\Issue\IssueResult;
use mglaman\DrupalOrg\Result\Maintainer\MaintainerIssuesResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestDiffResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestFilesResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestListResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestStatusResult;
use mglaman\DrupalOrg\Result\Project\ProjectIssuesResult;
Expand All @@ -23,6 +25,8 @@ final public function format(ResultInterface $result): string
$result instanceof ProjectReleasesResult => $this->formatProjectReleases($result),
$result instanceof MergeRequestListResult => $this->formatMergeRequestList($result),
$result instanceof MergeRequestStatusResult => $this->formatMergeRequestStatus($result),
$result instanceof MergeRequestFilesResult => $this->formatMergeRequestFiles($result),
$result instanceof MergeRequestDiffResult => $this->formatMergeRequestDiff($result),
default => throw new \InvalidArgumentException(
sprintf('Unsupported result type: %s', get_class($result))
),
Expand All @@ -36,4 +40,6 @@ abstract protected function formatMaintainerIssues(MaintainerIssuesResult $resul
abstract protected function formatProjectReleases(ProjectReleasesResult $result): string;
abstract protected function formatMergeRequestList(MergeRequestListResult $result): string;
abstract protected function formatMergeRequestStatus(MergeRequestStatusResult $result): string;
abstract protected function formatMergeRequestFiles(MergeRequestFilesResult $result): string;
abstract protected function formatMergeRequestDiff(MergeRequestDiffResult $result): string;
}
36 changes: 36 additions & 0 deletions src/Cli/Formatter/LlmFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use mglaman\DrupalOrg\Result\Issue\IssueForkResult;
use mglaman\DrupalOrg\Result\Issue\IssueResult;
use mglaman\DrupalOrg\Result\Maintainer\MaintainerIssuesResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestDiffResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestFilesResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestListResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestStatusResult;
use mglaman\DrupalOrg\Result\Project\ProjectIssuesResult;
Expand Down Expand Up @@ -182,6 +184,40 @@ protected function formatMergeRequestStatus(MergeRequestStatusResult $result): s
XML;
}

protected function formatMergeRequestFiles(MergeRequestFilesResult $result): string
{
$filesXml = '';
foreach ($result->files as $file) {
$path = $this->xmlEscape((string) $file['path']);
$newFile = (bool) $file['new_file'] ? 'true' : 'false';
$deletedFile = (bool) $file['deleted_file'] ? 'true' : 'false';
$renamedFile = (bool) $file['renamed_file'] ? 'true' : 'false';
$filesXml .= " <file>\n";
$filesXml .= " <path>{$path}</path>\n";
$filesXml .= " <new_file>{$newFile}</new_file>\n";
$filesXml .= " <deleted_file>{$deletedFile}</deleted_file>\n";
$filesXml .= " <renamed_file>{$renamedFile}</renamed_file>\n";
$filesXml .= " </file>\n";
}
return "<drupal_context>\n <merge_request_iid>{$result->iid}</merge_request_iid>\n <changed_files>\n{$filesXml} </changed_files>\n</drupal_context>";
}

protected function formatMergeRequestDiff(MergeRequestDiffResult $result): string
{
$sourceBranch = $this->xmlEscape($result->sourceBranch);
$targetBranch = $this->xmlEscape($result->targetBranch);
$diff = $this->cdataWrap($result->diff);

return <<<XML
<drupal_context>
<merge_request_iid>{$result->iid}</merge_request_iid>
<source_branch>{$sourceBranch}</source_branch>
<target_branch>{$targetBranch}</target_branch>
<diff>{$diff}</diff>
</drupal_context>
XML;
}

private function toIso8601(int $timestamp): string
{
return (new \DateTimeImmutable())->setTimestamp($timestamp)->format(\DateTimeInterface::ATOM);
Expand Down
36 changes: 36 additions & 0 deletions src/Cli/Formatter/MarkdownFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use mglaman\DrupalOrg\Result\Issue\IssueForkResult;
use mglaman\DrupalOrg\Result\Issue\IssueResult;
use mglaman\DrupalOrg\Result\Maintainer\MaintainerIssuesResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestDiffResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestFilesResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestListResult;
use mglaman\DrupalOrg\Result\MergeRequest\MergeRequestStatusResult;
use mglaman\DrupalOrg\Result\Project\ProjectIssuesResult;
Expand Down Expand Up @@ -136,4 +138,38 @@ protected function formatMergeRequestStatus(MergeRequestStatusResult $result): s
}
return implode("\n", $lines);
}

protected function formatMergeRequestFiles(MergeRequestFilesResult $result): string
{
$lines = [];
$lines[] = "# MR !{$result->iid} Changed Files";
$lines[] = '';
foreach ($result->files as $file) {
$path = (string) $file['path'];
$annotations = [];
if ((bool) $file['new_file']) {
$annotations[] = '*(new)*';
}
if ((bool) $file['deleted_file']) {
$annotations[] = '*(deleted)*';
}
if ((bool) $file['renamed_file']) {
$annotations[] = '*(renamed)*';
}
$suffix = $annotations !== [] ? ' ' . implode(' ', $annotations) : '';
$lines[] = "- {$path}{$suffix}";
}
return implode("\n", $lines);
}

protected function formatMergeRequestDiff(MergeRequestDiffResult $result): string
{
$lines = [];
$lines[] = "# MR !{$result->iid} Diff (`{$result->sourceBranch}` → `{$result->targetBranch}`)";
$lines[] = '';
$lines[] = '```diff';
$lines[] = $result->diff;
$lines[] = '```';
return implode("\n", $lines);
}
}