Skip to content
Closed
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
57 changes: 57 additions & 0 deletions .agents/skills/external/ibexa-documentation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
name: ibexa-documentation
description: Look up features, concepts, configuration, extension points, and back office workflows in the locally installed Ibexa DXP documentation. Use whenever working on an Ibexa DXP project and you need to know how something in Ibexa works before writing code, configuration, or answers.

Check failure on line 3 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L3

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 3, "column": 126}}}, "severity": "ERROR"}

Check failure on line 3 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L3

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 3, "column": 178}}}, "severity": "ERROR"}

Check failure on line 3 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L3

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 3, "column": 234}}}, "severity": "ERROR"}
---

# Ibexa DXP documentation

Check failure on line 6 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L6

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 6, "column": 3}}}, "severity": "ERROR"}

Check notice on line 6 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L6

[Ibexa.SentenceCapitalizationInHeadings] Use sentence-style capitalization in headings
Raw output
{"message": "[Ibexa.SentenceCapitalizationInHeadings] Use sentence-style capitalization in headings", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 6, "column": 3}}}, "severity": "INFO"}

The official Ibexa DXP documentation is installed as Markdown files in `vendor/ibexa/documentation-developer/`.

Check failure on line 8 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L8

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 8, "column": 14}}}, "severity": "ERROR"}

Check notice on line 8 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L8

[Ibexa.Passive] Try to avoid passive tense, when possible.
Raw output
{"message": "[Ibexa.Passive] Try to avoid passive tense, when possible.", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 8, "column": 38}}}, "severity": "INFO"}
It matches this project's Ibexa DXP release line (e.g. 5.0).

Check failure on line 9 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L9

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 9, "column": 27}}}, "severity": "ERROR"}
Always consult it before web searches or memory: it works offline, matches the installed version, and links directly to the code in `vendor/`.

It contains two documentation sets:

- `developer/` — APIs, configuration, extension points, tutorials. Mirrors https://doc.ibexa.co/en/latest/
- `user/` — back office, editorial and commerce workflows. Mirrors https://doc.ibexa.co/projects/userguide/en/latest/

Use the documentation for what the code cannot tell you:

- Concepts and the content model: content types, fields, locations,
versions, languages, and how they relate.
- Release notes and changes between versions: `developer/release_notes/`.
- Update and migration instructions: `developer/update_and_migration/`.
- Project and feature setup, configuration, and best practices: `developer/infrastructure_and_maintenance/`.

For method signatures and contracts, the code in `vendor/` is authoritative.
Use the documentation for the intent, concepts, and configuration around them.
When the documentation and the installed code don't match, the code is right.

## Finding topics

- Read the set's table of contents: `vendor/ibexa/documentation-developer/developer/llms.txt` (or `user/llms.txt`). Page titles are grouped by section, with relative links.

Check notice on line 31 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L31

[Ibexa.Passive] Try to avoid passive tense, when possible.
Raw output
{"message": "[Ibexa.Passive] Try to avoid passive tense, when possible.", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 31, "column": 129}}}, "severity": "INFO"}
- Search the sets directly: `grep -ril "<topic>" vendor/ibexa/documentation-developer/`.

## Conventions

- Links between pages are relative and work offline. Follow them for related topics.
- PHP API references link to the class source in this project's `vendor/` directory. If the target file doesn't exist, that package isn't installed.

## Keep documentation up to date

The package is versioned as `MAJOR_DXP_VERSION.MINOR_DXP_VERSION.DATE_OF_TAGGING_YYYYMMDD` and must be used with the matching Ibexa DXP release line.

Check notice on line 41 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L41

[Ibexa.Passive] Try to avoid passive tense, when possible.
Raw output
{"message": "[Ibexa.Passive] Try to avoid passive tense, when possible.", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 41, "column": 13}}}, "severity": "INFO"}

Check notice on line 41 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L41

[Ibexa.Passive] Try to avoid passive tense, when possible.
Raw output
{"message": "[Ibexa.Passive] Try to avoid passive tense, when possible.", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 41, "column": 101}}}, "severity": "INFO"}

Check failure on line 41 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L41

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 41, "column": 127}}}, "severity": "ERROR"}
For example, `5.0.20260101` is for Ibexa DXP 5.0.x releases.

Check failure on line 42 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L42

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 42, "column": 36}}}, "severity": "ERROR"}
New version is released when the documentation content is updated.

Check notice on line 43 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L43

[Ibexa.Passive] Try to avoid passive tense, when possible.
Raw output
{"message": "[Ibexa.Passive] Try to avoid passive tense, when possible.", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 43, "column": 13}}}, "severity": "INFO"}

Check notice on line 43 in .agents/skills/external/ibexa-documentation/SKILL.md

View workflow job for this annotation

GitHub Actions / vale

[vale] .agents/skills/external/ibexa-documentation/SKILL.md#L43

[Ibexa.Passive] Try to avoid passive tense, when possible.
Raw output
{"message": "[Ibexa.Passive] Try to avoid passive tense, when possible.", "location": {"path": ".agents/skills/external/ibexa-documentation/SKILL.md", "range": {"start": {"line": 43, "column": 56}}}, "severity": "INFO"}

To check whether the documentation contains all the latest updates, run:

``` bash
composer outdated --direct "ibexa/documentation-*"
```

To update it, run:

```bash
composer update ibexa/documentation-developer --no-scripts
```

Always pass `--no-scripts`: the package contains only Markdown files, so the slow post-update scripts (cache clear, asset and frontend builds) are unnecessary.
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* export-ignore
/.agents export-ignore=false
/developer export-ignore=false
/user export-ignore=false
/composer.json export-ignore=false
/LICENSE export-ignore=false
/README.md export-ignore=false
178 changes: 178 additions & 0 deletions .github/workflows/release_composer_package.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
name: "Release Composer package"

on:
schedule:
# Daily at 03:17 UTC. Fans out to every maintained version branch (see determine-branches).
- cron: "17 3 * * *"
workflow_dispatch: ~

jobs:
determine-branches:
runs-on: ubuntu-latest
outputs:
branches: ${{ steps.set.outputs.branches }}
steps:
- id: set
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
# Manual runs only release the branch the workflow was dispatched from.
branches='["${{ github.ref_name }}"]'
else
# Scheduled runs always execute in the default branch's context, so they must
# explicitly check out each maintained version branch instead of relying on
# GITHUB_REF. Extend this list as new branches become active / drop EOL ones.
branches='["5.0"]'
fi
echo "branches=${branches}" >> "$GITHUB_OUTPUT"

release:
needs: determine-branches
runs-on: ubuntu-latest
permissions:
# Needed to commit the generated Markdown and push a tag.
contents: write
strategy:
fail-fast: false
matrix:
branch: ${{ fromJson(needs.determine-branches.outputs.branches) }}

steps:
# Shallow checkout of the branch tip only. The generated Markdown is never
# pushed to the branch itself (see below), only tagged, so the diff target is
# the latest tag — fetched individually in "Find the last tag" instead of
# pulling the full history + every daily tag snapshot (which took minutes).
- uses: actions/checkout@v4
with:
ref: ${{ matrix.branch }}

- name: Check out user documentation
uses: actions/checkout@v4
with:
repository: ibexa/documentation-user
ref: ${{ matrix.branch }}
path: user-docs

- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.13"

- name: Install dependencies
run: |
python -m pip install --upgrade pip

Check warning

Code scanning / SonarCloud

Python dependencies should be locked to verified versions Medium

Using dependencies without locking resolved versions is security-sensitive. See more on SonarQube Cloud
# user-docs pins ibexa-llms-txt from the upstream git repo; drop that line —
# the editable install from this checkout (requirements.txt: -e .) already
# provides the plugin, and pip refuses two direct references to one package.
grep -v '^ibexa-llms-txt @' user-docs/requirements.txt > user-reqs-filtered.txt
pip install -r requirements.txt -r user-reqs-filtered.txt

Check warning

Code scanning / SonarCloud

Python package manager scripts should not be executed during installation Medium

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here. See more on SonarQube Cloud

Check warning

Code scanning / SonarCloud

Python dependencies should be locked to verified versions Medium

Using dependencies without locking resolved versions is security-sensitive. See more on SonarQube Cloud

- name: Setup PHP
uses: shivammathur/setup-php@v2

Check failure

Code scanning / SonarCloud

External GitHub Actions and workflows should be pinned to a commit hash High

Use full commit SHA hash for this dependency. See more on SonarQube Cloud
with:
php-version: "8.3"
coverage: none

# - name: Generate token
# id: generate_token
# uses: actions/create-github-app-token@v2
# with:
# app-id: ${{ secrets.AUTOMATION_CLIENT_ID }}
# private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }}
# owner: ${{ github.repository_owner }}

- name: Add composer keys for private packagist
run: |
composer config --global http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN
composer config --global github-oauth.github.com $GITHUB_TOKEN
env:
SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }}
SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }}
GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }} #${{ steps.generate_token.outputs.token }}

# Needed to resolve the PHP API classes referenced by the docs to
# their vendor/ source paths (dump_class_paths.php).
- uses: ramsey/composer-install@v3

Check failure

Code scanning / SonarCloud

External GitHub Actions and workflows should be pinned to a commit hash High

Use full commit SHA hash for this dependency. See more on SonarQube Cloud
with:
dependency-versions: highest

- name: Build developer documentation
run: mkdocs build --strict
env:
# The cards() macro versions its links from this (as on RTD);
# without it they'd point at en/latest instead of this branch.
READTHEDOCS_VERSION_NAME: ${{ matrix.branch }}

- name: Build user documentation
run: mkdocs build --strict
working-directory: user-docs
env:
READTHEDOCS_VERSION_NAME: ${{ matrix.branch }}

- name: Resolve PHP API classes to vendor paths
run: php tools/llm_package/dump_class_paths.php site user-docs/site class_paths.json

- name: Build package Markdown (developer/, user/)
run: python build_package_docs.py --version "${{ matrix.branch }}"

- name: Copy package README
run: cp tools/llm_package/README.package.md README.md

- name: Find the last tag for this branch
id: last_tag
env:
BRANCH: ${{ matrix.branch }}
run: |
# List tag names on the remote (no object download), then fetch only the
# latest one — the single commit the change check diffs against.
latest_tag=$(git ls-remote --tags origin "refs/tags/${BRANCH}.*" \
| awk '{print $2}' | sed 's|^refs/tags/||' | grep -v '\^{}$' \
| sort -t. -k1,1n -k2,2n -k3,3n -k4,4n | tail -1)
if [[ -n "$latest_tag" ]]; then
git fetch --depth=1 origin "refs/tags/${latest_tag}:refs/tags/${latest_tag}"
fi
echo "latest_tag=${latest_tag}" >> "$GITHUB_OUTPUT"

- name: Check for content changes since the last tag
id: changes
env:
LATEST_TAG: ${{ steps.last_tag.outputs.latest_tag }}
run: |
# The generated Markdown is never committed/pushed to the branch itself (only
# tagged), so there's nothing on the branch to diff against — compare the freshly
# built content to what the last tag captured instead. -f because developer/ and
# user/ are gitignored to keep local builds out of the working tree.
git add -f developer user
git add README.md
if [[ -z "$LATEST_TAG" ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
# .agents (agent skills, tracked on the branch) is part of the package too;
# include it so skill-only edits also produce a release.
elif git diff --cached --quiet "$LATEST_TAG" -- developer user README.md .agents; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

- name: Commit generated Markdown
if: steps.changes.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit -m "Update generated Markdown docs for ${{ matrix.branch }}"

- name: Tag release
if: steps.changes.outputs.changed == 'true'
env:
BRANCH: ${{ matrix.branch }}
run: |
# Push only the tag, never the branch — the branch stays exactly as authored,
# the generated Markdown exists solely as the commit this tag points to.
tag="${BRANCH}.$(date -u +%Y%m%d)"

if git rev-parse "$tag" >/dev/null 2>&1; then
echo "Tag $tag already exists, skipping."
exit 0
fi

git tag "$tag"
git push origin "$tag"
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ lychee-report.md
code_samples/_inline_php/
/build/
*.egg-info/
/doc/
/llms.txt
/developer/
/user/
/class_paths.json
/user-docs/
Loading
Loading