Skip to content

Commit c364ee4

Browse files
authored
Merge pull request #1216 from johnatas-x/mago-task
Add Mago as task
2 parents ccf187b + 75b50c8 commit c364ee4

16 files changed

Lines changed: 1400 additions & 0 deletions

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"atoum/atoum": "Lets GrumPHP run your unit tests.",
5454
"behat/behat": "Lets GrumPHP validate your project features.",
5555
"brianium/paratest": "Lets GrumPHP run PHPUnit in parallel.",
56+
"carthage-software/mago": "Lets GrumPHP help you write better PHP code.",
5657
"codeception/codeception": "Lets GrumPHP run your project's full stack tests",
5758
"consolidation/robo": "Lets GrumPHP run your automated PHP tasks.",
5859
"designsecurity/progpilot": "Lets GrumPHP be sure that there are no vulnerabilities in your code.",

doc/tasks.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ grumphp:
3232
infection: ~
3333
jsonlint: ~
3434
kahlan: ~
35+
mago_analyze: ~
36+
mago_format: ~
37+
mago_guard: ~
38+
mago_lint: ~
3539
make: ~
3640
npm_script: ~
3741
paratest: ~
@@ -99,6 +103,11 @@ Every task has its own default configuration. It is possible to overwrite the pa
99103
- [Infection](tasks/infection.md)
100104
- [JsonLint](tasks/jsonlint.md)
101105
- [Kahlan](tasks/kahlan.md)
106+
- [Mago](tasks/mago.md)
107+
- [Mago Analyzer](tasks/mago/analyzer.md)
108+
- [Mago Formatter](tasks/mago/formatter.md)
109+
- [Mago Guard](tasks/mago/guard.md)
110+
- [Mago Linter](tasks/mago/linter.md)
102111
- [Make](tasks/make.md)
103112
- [NPM script](tasks/npm_script.md)
104113
- [Paratest](tasks/paratest.md)

doc/tasks/mago.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Mago
2+
3+
[Mago](https://mago.carthage.software/) is a fast PHP toolchain written in Rust. It bundles a
4+
formatter, a linter, a static analyzer and an architectural guard. GrumPHP exposes each of these as
5+
its own task so you can enable only what you need and configure them independently.
6+
7+
## Composer
8+
9+
```bash
10+
composer require --dev carthage-software/mago
11+
```
12+
13+
Mago is configured through a single `mago.toml` file in your project root. You can scaffold one with:
14+
15+
```bash
16+
vendor/bin/mago init
17+
```
18+
19+
## Tasks
20+
21+
| Task | Description |
22+
| --- | --- |
23+
| [`mago_format`](mago/formatter.md) | Format PHP code to match your configured style. |
24+
| [`mago_lint`](mago/linter.md) | Run linting rules to catch style violations, code smells and likely bugs. |
25+
| [`mago_analyze`](mago/analyzer.md) | Deep static analysis: type checking, control-flow and logical-error detection. |
26+
| [`mago_guard`](mago/guard.md) | Enforce architectural rules and layer dependencies. |
27+
28+
## Behavior
29+
30+
`mago_format`, `mago_lint` and `mago_analyze` run read-only by default and, when they fail, GrumPHP
31+
offers to re-run them with fixes applied. `mago_guard` has no auto-fix — architectural violations
32+
cannot be fixed automatically, so it only reports them.
33+
34+
Each task scopes its work to the relevant files per context (pre-commit vs run). The exact behavior
35+
differs per task because of how Mago's CLI works — see each task's page below for the details and its
36+
full set of configurable options.

doc/tasks/mago/analyzer.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Mago Analyzer
2+
3+
Perform deep static analysis on PHP code including type checking, control flow analysis, and detection of logical errors.
4+
5+
## Composer
6+
7+
```bash
8+
composer require --dev carthage-software/mago
9+
```
10+
11+
## Behavior
12+
13+
The task runs `mago analyze` directly to get full diagnostic output. When running in a `git pre-commit` context, only staged files are analyzed (`--staged`). In a `run` context, all files are analyzed.
14+
15+
If the task fails, GrumPHP will offer to re-run with `--fix` applied. The fix mode can be configured via `fix-mode`.
16+
17+
## Config
18+
19+
The task lives under the `mago_analyze` namespace and has following configurable parameters:
20+
21+
```yaml
22+
# grumphp.yml
23+
grumphp:
24+
tasks:
25+
mago_analyze:
26+
no-stubs: ~
27+
retain-codes: []
28+
ignore-baseline: ~
29+
sort: ~
30+
fix-mode: safe
31+
minimum-report-level: ~
32+
```
33+
34+
**no-stubs**
35+
36+
*Type: bool*
37+
38+
Disable built-in PHP and library stubs for analysis. By default, the analyzer uses stubs for built-in PHP functions and popular libraries to provide accurate type information. Disabling this may result in more reported issues when external symbols can't be resolved.
39+
40+
**retain-codes**
41+
42+
*Type: string[] — Default: []*
43+
44+
Reporting filter: only display issues matching the specified rule codes (e.g. `invalid-argument`, `semantics`). All rules still run; only the output is filtered. Can be specified multiple times.
45+
46+
**ignore-baseline**
47+
48+
*Type: bool*
49+
50+
Ignore the baseline file and report all issues, including those currently suppressed. The baseline file must be generated manually via `mago analyze --generate-baseline`.
51+
52+
**sort**
53+
54+
*Type: bool*
55+
56+
Sort reported issues by severity level, rule code, and file location. By default, issues are reported in the order they appear in files.
57+
58+
**fix-mode**
59+
60+
*Default: safe — Possible values: `safe`, `potentially-unsafe`, `unsafe`*
61+
62+
Controls which fixes are applied when GrumPHP offers to auto-fix:
63+
64+
- `safe` — apply only safe fixes (default)
65+
- `potentially-unsafe` — also apply fixes that may require manual review
66+
- `unsafe` — also apply fixes that might change code behavior
67+
68+
**minimum-report-level**
69+
70+
*Default: null (mago default: all levels)*
71+
72+
Minimum severity level to display in the report. Issues below this level are not shown. Possible values: `note`, `help`, `warning`, `error`
73+

doc/tasks/mago/formatter.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Mago Formatter
2+
3+
Automatically format PHP code to match the configured style preferences.
4+
5+
## Composer
6+
7+
```bash
8+
composer require --dev carthage-software/mago
9+
```
10+
11+
## Behavior
12+
13+
The task always runs in `--dry-run` mode: it previews formatting changes without modifying any files, and fails if any file would be changed.
14+
15+
In a `run` context the whole project is checked (Mago uses the paths from your `mago.toml`). In a `git pre-commit` context the staged `.php` files are passed to Mago explicitly so only those files are checked. (`mago format --staged` cannot be combined with `--dry-run`, so the staged files are passed as paths instead — note this overrides the `source`/`excludes` config in `mago.toml` for those files, the same trade-off other file-based GrumPHP tasks make.)
16+
17+
If the task fails, GrumPHP will offer to re-run without `--dry-run` to apply the formatting in-place.
18+
19+
## Config
20+
21+
The task lives under the `mago_format` namespace and has no configurable parameters:
22+
23+
```yaml
24+
# grumphp.yml
25+
grumphp:
26+
tasks:
27+
mago_format: ~
28+
```

doc/tasks/mago/guard.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Mago Guard
2+
3+
Enforce architectural rules and layer dependencies. Checks that code follows defined architectural constraints, such as ensuring that certain layers don't depend on others.
4+
5+
## Composer
6+
7+
```bash
8+
composer require --dev carthage-software/mago
9+
```
10+
11+
## Behavior
12+
13+
The task runs `mago guard` and fails when an architectural violation is found. It runs on all files in both `git pre-commit` and `run` contexts (guard has no `--staged` mode, and architectural rules are evaluated against the whole project). Because every pre-commit run scans the full project, consider whether `mago_guard` is fast enough for your codebase before enabling it as a pre-commit task.
14+
15+
Guard does not offer an auto-fix: architectural violations cannot be fixed automatically, so the task only reports them.
16+
17+
## Config
18+
19+
The task lives under the `mago_guard` namespace and has following configurable parameters:
20+
21+
```yaml
22+
# grumphp.yml
23+
grumphp:
24+
tasks:
25+
mago_guard:
26+
mode: ~
27+
no-stubs: ~
28+
retain-codes: []
29+
ignore-baseline: ~
30+
sort: ~
31+
minimum-report-level: ~
32+
```
33+
34+
**mode**
35+
36+
*Default: null — Possible values: `structural`, `perimeter`*
37+
38+
Selects which guard checks run. These are mutually exclusive in Mago, so a single option is used instead of separate flags:
39+
40+
- `~` (not set) — run both structural and perimeter checks (Mago's default)
41+
- `structural` — run only structural checks (naming conventions, modifiers, inheritance constraints)
42+
- `perimeter` — run only perimeter checks (dependency boundaries, layer restrictions)
43+
44+
**no-stubs**
45+
46+
*Type: bool*
47+
48+
Disable built-in PHP and library stubs. By default, guard uses stubs for built-in PHP functions and popular libraries to provide accurate symbol information. Disabling this may result in more warnings when external symbols can't be resolved.
49+
50+
**retain-codes**
51+
52+
*Type: string[] — Default: []*
53+
54+
Reporting filter: only display issues matching the specified rule codes. All rules still run; only the output is filtered. Can be specified multiple times.
55+
56+
**ignore-baseline**
57+
58+
*Type: bool*
59+
60+
Ignore the baseline file and report all issues, including those currently suppressed. The baseline file must be generated manually via `mago guard --generate-baseline`.
61+
62+
**sort**
63+
64+
*Type: bool*
65+
66+
Sort reported issues by severity level, rule code, and file location. By default, issues are reported in the order they appear in files.
67+
68+
**minimum-report-level**
69+
70+
*Default: null (mago default: all levels)*
71+
72+
Minimum severity level to display in the report. Issues below this level are not shown. Possible values: `note`, `help`, `warning`, `error`

doc/tasks/mago/linter.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Mago Linter
2+
3+
Run linting rules on PHP code to identify style violations, code smells, and potential bugs.
4+
5+
## Composer
6+
7+
```bash
8+
composer require --dev carthage-software/mago
9+
```
10+
11+
## Behavior
12+
13+
The task always runs in `--fix --dry-run` mode: it previews what automatic fixes would be applied without modifying any files, and fails if issues are found. When running in a `git pre-commit` context, only staged files are linted (`--staged`). In a `run` context, all files are linted.
14+
15+
If the task fails, GrumPHP will offer to re-run with `--fix` applied. The fix mode can be configured via `fix-mode`.
16+
17+
## Config
18+
19+
The task lives under the `mago_lint` namespace and has following configurable parameters:
20+
21+
```yaml
22+
# grumphp.yml
23+
grumphp:
24+
tasks:
25+
mago_lint:
26+
semantics: ~
27+
pedantic: ~
28+
only: []
29+
retain-codes: []
30+
ignore-baseline: ~
31+
sort: ~
32+
fix-mode: safe
33+
minimum-report-level: ~
34+
```
35+
36+
**semantics**
37+
38+
*Type: bool*
39+
40+
Skip linter rules and only perform basic syntax and semantic validation. Checks that your PHP code parses correctly and has valid semantic structure, without applying any style or quality rules. Useful for quick syntax validation.
41+
42+
**pedantic**
43+
44+
*Type: bool*
45+
46+
Enable every available linter rule for maximum thoroughness. Overrides your configuration and enables all rules, including those disabled by default. The output will be extremely verbose and is not recommended for regular use. Useful for comprehensive code audits.
47+
48+
**only**
49+
50+
*Type: string[] — Default: []*
51+
52+
Run only the specified rules, ignoring the configuration file. Provide a list of rule codes (e.g. `invalid-argument`, `semantics`). Overrides your `mago.toml` configuration and is useful for targeted analysis.
53+
54+
**retain-codes**
55+
56+
*Type: string[] — Default: []*
57+
58+
Reporting filter: only display issues matching the specified rule codes (e.g. `invalid-argument`, `semantics`). All rules still run; only the output is filtered. Can be specified multiple times.
59+
60+
Note: this differs from `only`, which restricts which rules are executed.
61+
62+
**ignore-baseline**
63+
64+
*Type: bool*
65+
66+
Ignore the baseline file and report all issues, including those currently suppressed. The baseline file must be generated manually via `mago lint --generate-baseline`.
67+
68+
**sort**
69+
70+
*Type: bool*
71+
72+
Sort reported issues by severity level, rule code, and file location. By default, issues are reported in the order they appear in files.
73+
74+
**fix-mode**
75+
76+
*Default: safe — Possible values: `safe`, `potentially-unsafe`, `unsafe`*
77+
78+
Controls which fixes are applied when GrumPHP offers to auto-fix:
79+
80+
- `safe` — apply only safe fixes (default)
81+
- `potentially-unsafe` — also apply fixes that may require manual review
82+
- `unsafe` — also apply fixes that might change code behavior
83+
84+
**minimum-report-level**
85+
86+
*Default: null (mago default: all levels)*
87+
88+
Minimum severity level to display in the report. Issues below this level are not shown. Possible values: `note`, `help`, `warning`, `error`
89+

resources/config/tasks.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,34 @@ services:
169169
tags:
170170
- {name: grumphp.task, task: kahlan}
171171

172+
GrumPHP\Task\MagoAnalyzer:
173+
arguments:
174+
- '@process_builder'
175+
- '@formatter.raw_process'
176+
tags:
177+
- {name: grumphp.task, task: mago_analyze}
178+
179+
GrumPHP\Task\MagoFormatter:
180+
arguments:
181+
- '@process_builder'
182+
- '@formatter.raw_process'
183+
tags:
184+
- {name: grumphp.task, task: mago_format}
185+
186+
GrumPHP\Task\MagoGuard:
187+
arguments:
188+
- '@process_builder'
189+
- '@formatter.raw_process'
190+
tags:
191+
- {name: grumphp.task, task: mago_guard}
192+
193+
GrumPHP\Task\MagoLinter:
194+
arguments:
195+
- '@process_builder'
196+
- '@formatter.raw_process'
197+
tags:
198+
- {name: grumphp.task, task: mago_lint}
199+
172200
GrumPHP\Task\Make:
173201
arguments:
174202
- '@process_builder'

0 commit comments

Comments
 (0)