Skip to content

Commit 4591a03

Browse files
chore(doc) #80 Add missing documentations: reference pages for bundle configuration, process UI options, users & security, process executions & logs, scheduler, HTTP API, console commands and messenger, cookbooks and troubleshooting. Harmonize and fix existing documentation.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent bc97cfa commit 4591a03

16 files changed

Lines changed: 1137 additions & 178 deletions

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Latest
33

44
## Changes
55
* [#78](https://github.com/cleverage/ui-process-bundle/issues/78) Update quality stack: use Rector `withComposerBased()` sets (removed `SYMFONY_64` / `PHPUNIT_100` sets), declare used Symfony packages and PHPUnit range in composer.json, apply quality tools fixes
6+
* [#80](https://github.com/cleverage/ui-process-bundle/issues/80) Add missing documentations: reference pages for bundle configuration, process UI options, users & security, process executions & logs, scheduler, HTTP API, console commands and messenger, cookbooks and troubleshooting. Harmonize and fix existing documentation.
67

78
v3.0
89
------

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CleverAge/UiProcessBundle
22
=======================
33

44
This bundle is a part of the [CleverAge/ProcessBundle](https://github.com/cleverage/process-bundle) project.
5-
It provides a simple UX using [EasyAdmin](https://symfony.com/bundles/EasyAdminBundle/4.x/index.html) on Process bundle.
5+
It provides a simple UX using [EasyAdmin](https://symfony.com/bundles/EasyAdminBundle/current/index.html) on Process bundle.
66

77
Compatible with [Symfony stable version and latest Long-Term Support (LTS) release](https://symfony.com/releases).
88

‎docs/cookbooks/form_file_upload.md‎

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
Launch a CSV import from a form with file upload
2+
===============================================
3+
4+
This recipe lets a back-office user upload a CSV file from the UI, choose its delimiter, and import it. The launch
5+
form validates the file extension and the delimiter before the process is queued.
6+
7+
```yaml
8+
# config/packages/process/app.import_csv.yaml
9+
clever_age_process:
10+
configurations:
11+
app.import_csv:
12+
description: 'Import an uploaded CSV file'
13+
help: 'Ex: bin/console cleverage:process:execute app.import_csv --input=/path/to/file.csv -c delimiter:";"'
14+
entry_point: log_file # Required: the uploaded file path is sent to this task
15+
options:
16+
ui:
17+
source: CSV upload
18+
target: Logs
19+
ui_launch_mode: form
20+
entrypoint_type: file
21+
default:
22+
context:
23+
- key: delimiter
24+
value: ','
25+
constraints:
26+
- Collection:
27+
fields:
28+
input:
29+
- NotNull: ~
30+
- File:
31+
extensions: [csv]
32+
context:
33+
- Collection:
34+
fields:
35+
delimiter:
36+
- Choice:
37+
choices: [',', ';']
38+
message: 'delimiter context must be , or ;. {{ value }} given.'
39+
tasks:
40+
log_file:
41+
service: '@CleverAge\ProcessBundle\Task\Reporting\LoggerTask'
42+
options:
43+
level: info
44+
message: 'Read file'
45+
context: ['input']
46+
outputs: [read]
47+
48+
read:
49+
service: '@CleverAge\ProcessBundle\Task\File\Csv\InputCsvReaderTask'
50+
options:
51+
delimiter: '{{ delimiter }}' # Contextualized option, set from the launch form
52+
outputs: [log_line]
53+
54+
log_line:
55+
service: '@CleverAge\ProcessBundle\Task\Reporting\LoggerTask'
56+
options:
57+
level: info
58+
message: 'Read line'
59+
context: ['input']
60+
```
61+
62+
How it works:
63+
- `ui_launch_mode: form` makes the "Launch" action of the process list open a form instead of a confirmation modal
64+
(see [launch modes](../reference/02-process_ui_options.md#launch-modes)).
65+
- `entrypoint_type: file` turns the `input` field into a file upload. As the process has an `entry_point`, the field
66+
is required. The uploaded file is saved in the `upload_directory` directory and its path is sent to the
67+
`log_file` task (see [launch form](../reference/02-process_ui_options.md#launch-form)).
68+
- `default.context` pre-fills a `delimiter` line in the context collection
69+
(see [default values](../reference/02-process_ui_options.md#default-values)). It is injected into the
70+
`InputCsvReaderTask` through the `{{ delimiter }}` contextualized option, exactly like `-c delimiter:";"` on the
71+
console.
72+
- `constraints` validate the whole form data (`input` and `context`): the process is not queued while the file is not
73+
a CSV or the delimiter is not `,` or `;` (see [constraints](../reference/02-process_ui_options.md#constraints)).
74+
As the `Collection` constraint rejects extra fields, users cannot add other context values: add
75+
`allowExtraFields: true` to allow them.
76+
- On submit, a message is sent to the `execute_process` transport, so a `messenger:consume execute_process` worker
77+
must be running (see [messenger](../reference/08-messenger.md)). The connected user email is added to the context
78+
as `execution_user`.
79+
- The execution, its report and its logs are then available in "Process > Executions"
80+
(see [process executions & logs](../reference/04-process_executions_and_logs.md)).
81+
82+
Uploaded files are not removed after the execution: add a cleaning step at the end of the process (e.g. a
83+
[FileRemoverTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/file_remover_task.md)) or purge the `upload_directory` directory periodically.
84+
85+
The same process can also be launched through the [HTTP API](../reference/06-http_api.md), with a file upload:
86+
87+
```bash
88+
curl --location 'https://your-domain.com/http/process/execute' \
89+
--header 'Authorization: Bearer myBearerToken' \
90+
--form 'code="app.import_csv"' \
91+
--form 'input=@/path/to/file.csv' \
92+
--form 'context[delimiter]=";"'
93+
```
94+
95+
Note that the launch form `constraints` are not applied to HTTP API calls.

‎docs/cookbooks/http_api_launch.md‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
Launch a process through the HTTP API
2+
=====================================
3+
4+
This recipe lets another application (an ERP, a CI job, a webhook...) trigger a process, with parameters, through an
5+
HTTP request. Here, the calling application asks to fetch the communes of a postal code from a REST API.
6+
7+
```yaml
8+
# config/packages/process/app.fetch_communes.yaml
9+
clever_age_process:
10+
configurations:
11+
app.fetch_communes:
12+
description: 'Fetch the communes of a postal code'
13+
help: 'Ex: bin/console cleverage:process:execute app.fetch_communes -c codePostal:"46800"'
14+
public: true # Default value: private processes cannot be launched through the HTTP API
15+
options:
16+
ui:
17+
source: API Carto IGN
18+
target: Logs
19+
tasks:
20+
request:
21+
service: '@CleverAge\RestProcessBundle\Task\RequestTask'
22+
options:
23+
client: apicarto_ign
24+
url: '/codes-postaux/communes/{codePostal}'
25+
method: 'GET'
26+
url_parameters: { codePostal: '{{ codePostal }}' } # Contextualized option, set by the HTTP call
27+
outputs: [decode]
28+
29+
decode:
30+
service: '@CleverAge\ProcessBundle\Task\TransformerTask'
31+
options:
32+
transformers:
33+
json_decode: ~ # Generic transformer defined in the application
34+
outputs: [log]
35+
36+
log:
37+
service: '@CleverAge\ProcessBundle\Task\Reporting\LoggerTask'
38+
options:
39+
level: info
40+
message: 'Communes fetched'
41+
context: ['input']
42+
```
43+
44+
First, create a technical user for the calling application, e.g.
45+
`bin/console cleverage:ui-process:user-create erp@example.com 'a-long-random-password'`. Then, in the UI, open
46+
"Users > User List", edit this user and click on "Generate token". Copy the token displayed in the flash message: it
47+
will never be displayed again.
48+
49+
The calling application can now queue the process:
50+
51+
```bash
52+
curl --location 'https://your-domain.com/http/process/execute' \
53+
--header 'Authorization: Bearer myBearerToken' \
54+
--header 'Content-Type: application/json' \
55+
--data '{
56+
"code": "app.fetch_communes",
57+
"context": {"codePostal": "46800"}
58+
}'
59+
```
60+
61+
Response:
62+
63+
```json
64+
"Process has been added to queue. It will start as soon as possible."
65+
```
66+
67+
How it works:
68+
- The `Authorization: Bearer` header is checked against the hashed token of the users
69+
(see [authentication](../reference/06-http_api.md#authentication)). A missing or invalid token returns a `401`.
70+
- `code` must be the code of an existing, public process, otherwise a `422` is returned with the violation message
71+
(see [parameters](../reference/06-http_api.md#parameters)).
72+
- `context` values are injected into the contextualized options, like `-c codePostal:"46800"` on the console. With
73+
form data instead of JSON, send them as `--form 'context[codePostal]="46800"'`.
74+
- By default, the process is queued to the `execute_process` transport and executed by a
75+
`messenger:consume execute_process` worker (see [messenger](../reference/08-messenger.md)): the HTTP response does
76+
not wait for the end of the process. Add `"queue": false` to execute it during the request: the response is then
77+
`200` if the process succeeded, or `500` with the exception message.
78+
- The execution, its logs and its report are available in "Process > Executions", like any other execution
79+
(see [process executions & logs](../reference/04-process_executions_and_logs.md)).
80+
81+
The `apicarto_ign` client is a [RestProcessBundle](https://github.com/cleverage/rest-process-bundle) client registered
82+
in the application (a `CleverAge\RestProcessBundle\Client\Client` service with `$uri: 'https://apicarto.ign.fr/api'`,
83+
tagged `cleverage.rest.client`), and `json_decode` a generic transformer (see
84+
[generic transformers](https://github.com/cleverage/process-bundle/blob/main/docs/reference/03-generic_transformers_definition.md)).
85+
To send a file to the process instead, see the file upload example of the
86+
[form with file upload](form_file_upload.md) cookbook.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
Schedule a recurring process
2+
============================
3+
4+
This recipe runs a Doctrine purge process every night, and lets operators change its schedule or its parameters from the UI
5+
without any deployment.
6+
7+
```yaml
8+
# config/packages/process/app.purge_authors.yaml
9+
clever_age_process:
10+
configurations:
11+
app.purge_authors:
12+
description: 'Remove the authors with a given lastname, and their books'
13+
help: 'Ex: bin/console cleverage:process:execute app.purge_authors -c lastname:"King"'
14+
options:
15+
ui:
16+
source: Database
17+
target: Database
18+
ui_launch_mode: form # Manual launches from the process list can set the lastname too
19+
default:
20+
context:
21+
- key: lastname
22+
value: King
23+
tasks:
24+
read:
25+
service: '@CleverAge\DoctrineProcessBundle\Task\EntityManager\DoctrineReaderTask'
26+
options:
27+
class_name: 'App\Entity\Author'
28+
criteria:
29+
lastname: '{{ lastname }}' # Contextualized option, set by the schedule
30+
outputs: [log, remove]
31+
32+
log:
33+
service: '@CleverAge\ProcessBundle\Task\Reporting\LoggerTask'
34+
options:
35+
level: warning # Counted in the execution report
36+
message: 'Removing author'
37+
38+
remove:
39+
service: '@CleverAge\DoctrineProcessBundle\Task\EntityManager\DoctrineRemoverTask'
40+
```
41+
42+
Then, in the UI, open "Process > Scheduler" and create a schedule:
43+
44+
| Tab | Field | Value |
45+
|---------|------------|------------------------------------------|
46+
| General | Process | `app.purge_authors` |
47+
| General | Type | `cron` |
48+
| General | Expression | `0 3 * * *` (every day at 3 AM) |
49+
| Input | Input | *(empty)* |
50+
| Context | Context | key `lastname`, value `King` |
51+
52+
Finally, make sure both workers are running, and restart the `scheduler_cron` one so that it loads the new schedule:
53+
54+
```bash
55+
bin/console messenger:consume scheduler_cron
56+
bin/console messenger:consume execute_process
57+
```
58+
59+
How it works:
60+
- The process must be public (the default) to be selectable in the scheduler
61+
(see [process visibility](../reference/02-process_ui_options.md#process-visibility)). The `ui` options only
62+
concern manual launches from the process list: they are not used by the scheduler.
63+
- The schedule is stored as a `ProcessSchedule`. Its expression is validated according to its type: a cron
64+
expression for `cron`, a relative time such as `10 minutes` for `every` (see
65+
[process schedules](../reference/05-scheduler.md#process-schedules)). The schedules list displays the next
66+
execution date.
67+
- The `scheduler_cron` worker loads the schedules when it starts. When one is due, it dispatches the process, with the
68+
schedule input and context, to the `execute_process` transport, where the other worker executes it
69+
(see [how it works](../reference/05-scheduler.md#how-it-works) and [messenger](../reference/08-messenger.md)).
70+
- The context pairs of the schedule are injected into the contextualized options, like `-c lastname:King` on the
71+
console: the same process can be scheduled several times with different contexts.
72+
- Each run appears in "Process > Executions" with its status, duration and a report counting the `Warning` logs, i.e.
73+
the number of removed authors (see [report](../reference/04-process_executions_and_logs.md#report)).
74+
75+
In production, keep the workers alive with Supervisor (see [workers](../reference/08-messenger.md#workers)), and
76+
restart the `scheduler_cron` worker after each change in the scheduler, e.g. with
77+
`bin/console messenger:stop-workers`.

0 commit comments

Comments
 (0)