Méthodes47
protected function actionItem(string $ticket, string $title, array $check): array| $ticket | string | |
| $title | string | the item's |
| $check | array | |
| retourne | array | its item, in the group of these (actions), a section per type |
function build(): array| retourne | array | the items, in the order the page shows them: written by hand, the code, the pages |
One item per file changed in a repository.
protected function changes(array $repository): voidstatic function CheckBlock(string $markdown): array| $markdown | string | |
| retourne | array | string, check: string, url: ?string, as?: string}|array{type: string, cells: list<string>, as?: string}> the lines of its last ``` `check `` block: page | what to check, page | url | what to check; or, when the first cell is one of them, diff | repository:path | what to read, run | command | expected | repository, decision | question | option 1 / option 2, manual | command or step | what to do` -- their cells after the first |
ChecklistBuilder::CheckBlock("```check\nhome | the logo is whole\n```"); // [['page' => 'home', 'check' => 'the logo is whole', 'url' => null]]ChecklistBuilder::CheckBlock("```check\nrun | phpunit | OK\n```"); // [['type' => 'run', 'cells' => ['phpunit', 'OK']]]ChecklistBuilder::CheckBlock("```check\ngestion | gestion/accidents | only its AT | as=limited\n```"); // [[..., 'as' => 'limited']]: a last cell `as=<key>` is the test account (@see TestAccounts)
function checksOf(string $id): array| $id | string | |
| retourne | array | string, check: string, url?: ?string, as?: string}|array{type: string, cells: list<string>, asked?: ?string, as?: string}> the functional checks of a ticket -- a page's, or another type's (CheckBlock): from the recipe's checks, else from the last ``` `check ``` block of its discussion, else of its description |
function commandAction(
string $command,
?string $folder,
string $expect,
array $notes,
string $group
): array- Voir
$localNote ($notes: on the instance, after a backup...) and the server runs the command ($runnable) in a folder of the recipe; else a manual, the command to copy (cd folder && ...)
| $command | string | |
| $folder | null | string | where it runs, as written (~/dev/src/acme) |
| $expect | string | what it prints when it passes |
| $notes | array | what the line says besides (ligne de commande, dev.oviepro.com) |
| $group | string | the item's |
| retourne | array | a run when the item's group runs commands (runsIn), nothing is said besides it but |
function commandOf(string $cell, string $rest): ?array| $cell | string | the second cell of a ``` `check ``` line |
| $rest | string | the cells after it, | between them |
| retourne | null | array | string, 1: ?string, 2: list<string>, 3: string}|null [command, folder, notes, expected] when the cell is a command ($command): its parentheses ((ligne de commande), (sur l'instance, après une sauvegarde)) and what follows the command (puis une seconde fois) are notes, cd folder && ... and folder (command) give its folder; a pipeline or a quote the block's | cut is put back together; null for what is not a command |
$builder->commandOf('(ligne de commande) php admin.php x --json', 'valid json'); // ['php admin.php x --json', null, ['ligne de commande'], 'valid json']
protected function copied(string $command, ?string $folder): string| $command | string | |
| $folder | null | string | |
| retourne | string | $command as it is copied: cd {folder} && {command} when it runs in a folder |
What the machine finds in a command's output when it passed, by family (the `cd {folder} &&` before it left aside):
- `php tools/mmo.php verify|i18n`: its last line `ok.`, never `failed:`;
- `phpunit`: `OK (`, never `FAILURES!` nor `ERRORS!`;
- `npm test`: `0 failed` (mmo.client's runner: « 505 passed, 0 failed »); `node --test`: `fail 0`;
- `php admin.php ...` (a dry run, a listing that only reads): the framework's `END(200)`, never an error (`!! `, its
`!! END(500) !!`, `Uncaught`, `Fatal error`);
- `mongosh ... DRY_RUN`: `dry run` (each part of a patch says « (dry run: nothing written) »), never a mongo error;
- `php scripts/check-release.php`: its summary, `point(s) prouvé(s)`; `php scripts/admin.php plan`: `versions`.static function DeriveMatch(string $command): array| $command | string | |
| retourne | array | string, notMatch?: string} nothing for another command: its expect decides, as before |
ChecklistBuilder::DeriveMatch('cd ~/dev/src/acme && phpunit --filter x'); // ['match' => '/^OK \(/m', 'notMatch' => '/FAILURES!|ERRORS!/']
A diff action written by hand without its revisions gets them: before committing (the recipe's beforeCommit group), what is about to be committed -- from HEAD to the working tree --; else what changed since the last release (release).
protected function diffRange(array $action, string $group): arraystatic function ExpandBraces(string $text): string| $text | string | |
| retourne | string | $text with its a/{b,c}.d written out: a/b.d a/c.d, the way an agent names several files at once |
ChecklistBuilder::ExpandBraces('src/views/{A,B}.jhs'); // 'src/views/A.jhs src/views/B.jhs'
Give each check opening a page -- or a request sent by hand -- the test account it is done as: the profile its
```` ```check ```` line names (`as=<key>`) or its item already gives (`action.as`), else the one whose `match` is
found first in its text (the check, then its page's name; an item written by hand: its title and detail). A
command to copy is no one's. Without profiles, the words [`$account`](https://mmoframework.fr/fr/documentation/mmo.admin/php/helpers/ChecklistBuilder.md#checklistbuilder-account) found stay.protected function giveAccounts(): voidthe items of items and itemsFile
protected function handWritten(): voidstatic function Home(): string| retourne | string | the home folder of the application folder's owner, else of the process |
The action of an item written by hand that gives none: its first command in code -- of its title, else of its detail -- run by the server when it is on the list ($runnable; cd {folder} && ... runs it in that repository) and the item's group runs commands (runsIn), else copied (manual); else its page (url).
function inferAction(array $item): ?array$builder->inferAction(['title' => '`php tools/mmo.php verify --lib=admin` passes']); // ['type' => 'run', 'command' => 'php tools/mmo.php verify --lib=admin', ...]
A ``` `check `` line's match= / notMatch= cells (a text, or a /regular expression/`): what the machine finds in a run's output, taken out of $cells.
static function MatchCells(array &$cells): array| $cells | array | |
| retourne | array | string, notMatch?: string} |
ChecklistBuilder::MatchCells($cells); // ['match' => '/\d+ pages en 200/'], $cells without that cell
function mentions(string $path): array| $path | string | a file, from its repository |
| retourne | array | the treated tickets whose discussion cites it: by its path, or by its last three or two parts |
Items doing the same thing (Signature) are one: the first keeps its place (group, section) and gets the tickets of all, its title says how many it stands for -- a new title, so a new id: a box ticked for one of them is not ticked for all --, its detail what each other one was for. A merged diff reads a range of commits, never the working tree alone, and its detail lists the commits touching its path (the newest $maxCommits): one file changed by several tickets is read once, commit by commit.
function merge(array $items): array$builder->merge([['title' => 'A', 'action' => ['type' => 'run', 'command' => 'phpunit']], ['title' => 'B', 'action' => ['type' => 'run', 'command' => 'phpunit']]]);
// [['title' => 'A (+ 1 more)', 'detail' => "Also: B", ...]]
A merged diff reads commits: from the oldest revision of its items (a later one is a commit since it; HEAD becomes the last release), to its branch -- to the working tree only while its path has changes not committed.
protected function mergedDiff(array &$action, array $others = []): string| $action | array | the diff, changed in place |
| $others = [] | array | the diffs of the same path merged into it |
| retourne | string | the commits from its old revision to its new one touching its path ($texts commits), '' when git says none |
function meta(): array| retourne | array | list<string>, types: array<string, array{label: string, icon: string}>, groups: array<string, array{icon: string}>, round: string} what the last build read besides the items: the members of a page by page file, what each type of check is called (the file's types, the recipe's over them), each section's icon, the round the file asks for ('' for none) |
static function Notes(string $text): array| $text | string | |
| retourne | array | list<string>, 1: string} the parentheses $text starts with, and what follows them |
ChecklistBuilder::Notes('(ligne de commande) php admin.php x'); // [['ligne de commande'], 'php admin.php x']
static function OpenQuote(string $command): bool| $command | string | |
| retourne | bool | whether $command leaves a quote open: a ' or " that starts or ends a word -- not an apostrophe between two letters (sur l'instance) |
ChecklistBuilder::OpenQuote("phpunit --filter 'testA"); // true
function orphans(): array| retourne | array | the titles of the code items no ticket cites |
function pageAction(string $url, string $check): array| $url | string | |
| $check | string | what to check there |
| retourne | array | a page action: as whom ($account), and the check's steps (; between them) |
one item per functional check of a treated ticket
protected function pageChecks(): voidstatic function Path(string $path): string| $path | string | |
| retourne | string | a path of the recipe: ~/ is the home folder of whoever owns the application's folder -- the developer, not the web server running the request -- {root}... as filename |
ChecklistBuilder::Path('~/dev/src/acme'); // '/home/marc/dev/src/acme'
static function Placeholders(string $address): array| $address | string | |
| retourne | array | the placeholders of an address that say which record: <un AT> as « un AT », {id d'une DAT} as « une DAT »; not …, nor a bare {id} |
ChecklistBuilder::Placeholders("analyse?id=<id d'un AT>"); // ['un AT']
protected function recordUrl(string $ticket, string $path, string $query): ?string| $ticket | string | |
| $path | string | an address's path (declaration/AccidentTravail) |
| $query | string | its query, with a placeholder (?id=<un AT>) |
| retourne | null | string | the same address with a record the ticket names in its discussion or its description (declaration/AccidentTravail?id=6979c45fbdc48981440b1d82), the first one; null for none |
function release(string $root): array| $root | string | a repository's folder |
| retourne | array | ?string, to: ?string} the changes since its last release: from its most recent v* tag the branch holds, or its last version X.Y.Z commit of mmo.json (mmo.admin's release, which tags nothing) when that one is later -- to its branch; nulls when git says neither |
$builder->release('/home/marc/dev/src/acme'); // ['from' => 'v5.0.0', 'to' => 'develop']
function repository(string $label): ?array| $label | string | a repository of the recipe, by its label (or its folder's name) |
| retourne | null | array | the recipe's repository |
protected function repositoryAt(string $folder): ?string| $folder | string | |
| retourne | null | string | the label of the recipe's repository in $folder (~/dev/src/acme), null for none |
The recipe's runFolders: folders a ▶ may run a command in (cd {folder} && ...) besides its repositories -- a hub and its libraries, for a checklist that lists no code (the front testers') --, no item made of them.
static function RunFolders(array $recipe): array| $recipe | array | |
| retourne | array | string> their paths, by label: an entry's label, else the folder as written (~/dev/src/MMO/master) |
ChecklistBuilder::RunFolders(['runFolders' => ['~/dev/src/MMO/master']]); // ['~/dev/src/MMO/master' => '/home/marc/dev/src/MMO/master']
function runsIn(string $group): bool| $group | string | an item's |
| retourne | bool | whether a command of its items the server runs gets a ▶: the recipe's runGroups name it when they are given, else its noRunGroups (a release's groups, whose commands are a server's) do not |
(new ChecklistBuilder(['noRunGroups' => ['release dev']]))->runsIn('release dev'); // false
function screen(string $page, ?string $path): ?string| $page | string | the name of a screen |
| $path | null | string | the path of an address that needs a record |
| retourne | null | string | the url of $screens for it: by its name (any case), else by its path or the closest parent |
The action of a page's check whose second cell is not an address to open as it is:
- a delivery ([`$delivery`](https://mmoframework.fr/fr/documentation/mmo.admin/php/helpers/ChecklistBuilder.md#checklistbuilder-delivery): `Livraison stg | php admin.php atonline-reimport | ...`): `manual`, a server is a person's;
- a command ([`commandOf`](https://mmoframework.fr/fr/documentation/mmo.admin/php/helpers/ChecklistBuilder.md#checklistbuilder-commandof): `php admin.php ... --dry-run`, `(ligne de commande) ...`, `cd folder && ...`,
`~/folder (command)`): [`commandAction`](https://mmoframework.fr/fr/documentation/mmo.admin/php/helpers/ChecklistBuilder.md#checklistbuilder-commandaction) -- a `run` when the server runs it and its group runs commands, else `manual`;
- a request (`POST maladie.pdf`, `(outils réseau) POST ...`, an `.json` address with a placeholder): `manual`;
- an address with a placeholder (`declaration/AccidentTravail/documents?id=<un AT>`): the same address with a record
the ticket names (`?id=6979c45f...`), else the screen that lists them ([`$screens`](https://mmoframework.fr/fr/documentation/mmo.admin/php/helpers/ChecklistBuilder.md#checklistbuilder-screens)), its first step saying which to open;
- a screen named without its address (`(menu du compte) Profil`): the address another check of the ticket gives it,
else [`$screens`](https://mmoframework.fr/fr/documentation/mmo.admin/php/helpers/ChecklistBuilder.md#checklistbuilder-screens);
- else `manual`: what the cells say, as steps.function screenAction(string $ticket, array $check, array $siblings = []): array$builder->screenAction('12', ['page' => 'Profil', 'url' => '(menu du compte) Profil', 'check' => 'saved']); // a `page` of $screens['Profil']
function section(string $path, bool $pages = true): string| $path | string | a file, from its repository |
| $pages = true | bool | whether src/pages holds the pages of an application (mmo.client): a page is then in its page's section |
| retourne | string | its section: its folder, two or three levels deep; a page's folder for a page |
protected function sectionsItems(array $json): array| $json | array | {sections: [{label, icon, recheck, pages: [{label, path, note, recheck, checks: [{label, type, recheck}]}]}]} |
| retourne | array | one item per check: the section is the group, the page the section; a check's recheck is its own, else its page's, else its section's |
static function Shown(string $path): string| $path | string | |
| retourne | string | $path as an item shows it: the home folder as ~ |
static function Signature(array $item): ?string| $item | array | |
| retourne | null | string | what the item does, the same for items that check the same thing: a diff its repository and path; a command (run, or copied) itself, where and what it must print; a page its address, account and steps; a decision its ticket and question; null for an item without an action, a page without steps, or a step by hand without one |
function source(): ?string| retourne | null | string | what the items depend on when they come from the recipe alone (items, itemsFile): its hash, which changes when the file or the recipe does; null for a recipe reading repositories or a board, which only a build says |
(new ChecklistBuilder(['itemsFile' => '{root}/checklists/general.json']))->source(); // 'a3f1...'
static function Status(string $root): array| $root | string | a repository |
| retourne | array | string, 1: string}> [state, path] for each changed file: M, D, ??, A, R, T |
function treatedTickets(): array| retourne | array | the ids of the tickets treated, $treated, plus those of checks |
function unmatched(): array| retourne | array | the treated tickets no code item names: fixed without a change, or cited in a form the search misses |
function unmatchedAccounts(): array| retourne | array | string, title: string, text: string, as: ?string}> the checks of the last build that speak of an account (TestAccounts::MENTION) -- or name one, as= -- that no profile of the recipe's accounts knows: their item's id, title, the text read, what as said |
protected function url(?string $url): ?string| $url | null | string | |
| retourne | null | string | $url, relative to the recipe's site when it is relative; null for none, or for what is not a path |
protected function withSteps(array $action, string $cell): array| $action | array | |
| $cell | string | |
| retourne | array | $action with $cell before its steps: (menu du compte) Profil as « menu du compte : Profil » |
function __construct(array $recipe, ?MMO\admin\helpers\KanbanBoard $board = null)