Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bd0fc1e
6869: Add agents.md and Claude Code configuration
turegjorup Mar 19, 2026
1e7c04c
&869: Update Chnagelog
turegjorup Mar 19, 2026
30a9a53
6869: Update Changelog
turegjorup Mar 19, 2026
7b21a00
Merge branch 'feature/6869_agent_config' of github.com:itk-dev/devops…
turegjorup Mar 19, 2026
3d5ac2d
6869: Rename agents.md to claude.md and update settings
turegjorup Mar 25, 2026
864a7ca
Merge remote-tracking branch 'origin/develop' into feature/6869_agent…
turegjorup Mar 25, 2026
f07447d
Update .claude/settings.json
turegjorup Mar 25, 2026
8c33faf
6869: Add PHPStan job to PR workflow
turegjorup Mar 25, 2026
4b47640
6869: Improve Claude Code hooks and permissions
turegjorup Mar 25, 2026
560e5e5
6869: Clarify local-only dev credentials in docker-compose.override
turegjorup Mar 25, 2026
82b77ae
Merge branch 'feature/6869_agent_config' of github.com:itk-dev/devops…
turegjorup Mar 25, 2026
2ad001c
6869: Update claude.md for Symfony 8.0 and PHP 8.5
turegjorup Mar 25, 2026
9a88a00
6869: Fix typo in config reference (@var → @type)
turegjorup Mar 25, 2026
9344dca
6869: Fix FieldCollection::new() removed in EasyAdmin 5.x
turegjorup Mar 27, 2026
39144a6
6869: Update task file with "pr.actions" check
turegjorup Mar 27, 2026
84caedc
6869: Update defaults in claude.md
turegjorup Mar 27, 2026
506969b
6869: Add automation recommendations (agents, skills, hooks, MCP)
turegjorup Mar 27, 2026
5da6d06
6869: Fix hook file paths for Docker and update README
turegjorup Mar 27, 2026
bac1888
6869: Fix markdown lint errors in README.md
turegjorup Mar 27, 2026
7cf1f1e
Change agents.md to claude.md in Readme
turegjorup Apr 7, 2026
1f44f69
Use Symfony's when@dev to disable oidc in dev mode
turegjorup Apr 7, 2026
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
107 changes: 107 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to play with experimental as default in projects? 😊

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

},
"permissions": {
"allow": [
"Bash(cat:*)",
"Bash(diff:*)",
"Bash(echo:*)",
"Bash(find:*)",
"Bash(gh:*)",
"Bash(git:*)",
"Bash(grep:*)",
"Bash(head:*)",
"Bash(ls:*)",
"Bash(pwd)",
"Bash(tail:*)",
"Bash(tree:*)",
"Bash(wc:*)",
"Bash(which:*)",
"Bash(docker compose:*)",
"Bash(docker network:*)"
],
"deny": [
"Bash(rm -rf:*)",
"Read(./.env.local)",
"Read(./.env.local.*)",
"Read(./config/secrets/*)"
],
"ask": [
"Bash(gh issue create:*)",
"Bash(gh issue close:*)",
"Bash(gh issue delete:*)",
"Bash(gh issue edit:*)",
"Bash(gh issue comment:*)",
"Bash(gh pr create:*)",
"Bash(gh pr close:*)",
"Bash(gh pr merge:*)",
"Bash(gh pr edit:*)",
"Bash(gh pr comment:*)",
"Bash(gh pr review:*)",
"Bash(gh release create:*)",
"Bash(gh release delete:*)",
"Bash(gh release edit:*)",
"Bash(gh repo create:*)",
"Bash(gh repo delete:*)",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move to deny, and lets the human delete?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All "delete" commands have been moved to "deny"

"Bash(gh label create:*)",
"Bash(gh label delete:*)",
"Bash(gh label edit:*)",
"Bash(git push:*)",
"Bash(git branch -d:*)",
"Bash(git branch -D:*)",
"Bash(git tag -d:*)",
"Bash(git tag -a:*)",
"Bash(git tag :*)",
"Bash(git reset:*)",
"Bash(git rebase:*)",
"Bash(git merge:*)",
"Bash(git stash drop:*)",
"Bash(git clean:*)",
"Bash(git checkout -- :*)",
"Bash(git restore:*)",
"Bash(git commit:*)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "case \"$CLAUDE_FILE_PATH\" in *.php) docker compose exec -T phpfpm vendor/bin/php-cs-fixer fix --quiet \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac",
"timeout": 30
},
{
"type": "command",
"command": "case \"$CLAUDE_FILE_PATH\" in *.yaml|*.yml) docker compose exec -T phpfpm bin/console lint:yaml \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac",
"timeout": 15
},
{
"type": "command",
"command": "case \"$CLAUDE_FILE_PATH\" in *.twig) docker compose exec -T phpfpm bin/console lint:twig \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac",
"timeout": 15
},
{
"type": "command",
"command": "case \"$CLAUDE_FILE_PATH\" in *.json) python3 -m json.tool \"$CLAUDE_FILE_PATH\" > /dev/null 2>&1 || true ;; esac",
"timeout": 10
}
]
}
]
},
"enabledPlugins": {
"php-lsp@claude-plugins-official": true,
"code-simplifier@claude-plugins-official": true,
"context7@claude-plugins-official": true,
"code-review@claude-plugins-official": true,
"security-guidance@claude-plugins-official": true,
"playwright@claude-plugins-official": true,
"feature-dev@claude-plugins-official": true
Comment thread
turegjorup marked this conversation as resolved.
Outdated
},
"alwaysThinkingEnabled": true,
"defaultMode": "acceptEdits"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this should be the default behavior, it will not match all users workflow. The "alwaysThinkingEnabled" will burn tokens and time way to fast. It is better to do "ultrathink" when you need it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

}
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- [#58](https://github.com/itk-dev/devops_itksites/pull/58)
5002: Added export to everything
- [#62](https://github.com/itk-dev/devops_itksites/pull/62)
6869: Add agents.md and Claude Code configuration for AI coding agents

## [1.8.10] - 2025-07-02

Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[![Codecov](https://img.shields.io/codecov/c/github/itk-dev/devops_itksites?style=flat-square&logo=codecov)](https://codecov.io/gh/itk-dev/devops_itksites)
[![GitHub last commit](https://img.shields.io/github/last-commit/itk-dev/devops_itksites?style=flat-square)](https://github.com/itk-dev/devops_itksites/commits/develop/)
[![GitHub License](https://img.shields.io/github/license/itk-dev/devops_itksites?style=flat-square)](https://github.com/itk-dev/devops_itksites/blob/develop/LICENSE)
[![agents.md](https://img.shields.io/badge/%F0%9F%A4%96_agents.md-AI%20ready-8A2BE2?style=flat-square)](https://github.com/itk-dev/devops_itksites/blob/develop/agents.md)


This is our internal server and site registration tool. It works in tandem with our
Expand Down Expand Up @@ -125,3 +126,34 @@ during development to automatically rebuild assets when source files change.
```sh
docker compose run --rm node yarn coding-standards-check
```

### 🤖 AI coding agents

This project includes an [`agents.md`](agents.md) file that provides project
Comment thread
turegjorup marked this conversation as resolved.
Outdated
context for AI coding agents. The file describes the project architecture,
technology stack, development commands, CI/CD setup, and coding conventions.

`agents.md` is a vendor-neutral standard supported by tools such as
[Claude Code](https://claude.ai/claude-code),
[OpenCode](https://opencode.ai/), and others.

Tool-specific configuration (permissions, hooks, plugins) lives in `.claude/`
and is not portable across tools.

#### Claude Code plugins

The following plugins are enabled in `.claude/settings.json`:

| Plugin | Purpose | Source |
|---|---|---|
| `php-lsp` | PHP language server for type-aware code intelligence | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
| `context7` | Up-to-date documentation lookup for Symfony, Doctrine, API Platform, etc. | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
| `code-review` | Pull request code review | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
| `code-simplifier` | Suggests clarity and maintainability improvements | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
| `security-guidance` | Flags potential security issues (OWASP, injection, etc.) | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
| `playwright` | Browser automation for debugging and testing the EasyAdmin UI | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
| `feature-dev` | Guided feature development with codebase exploration and architecture focus | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |

> **Note:** The `php-lsp` plugin requires [Intelephense](https://intelephense.com/)
> installed globally: `npm install -g intelephense`. All other plugins work
> without additional dependencies.
142 changes: 142 additions & 0 deletions agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# 🤖 Code Agents - DevOps ITKsites

## Project Overview

**DevOps ITKsites** is an internal Symfony application for server and site
registration/monitoring at ITK Dev. It receives `DetectionResults` from the
[ITK sites server harvester](https://github.com/itk-dev/devops_itkServerHarvest)
and processes them asynchronously to track servers, sites, domains, Docker
images, packages, modules, CVEs, and git repositories.

## Technology Stack

- **Language**: PHP 8.4+ (Symfony 7.3)
- **API**: API Platform 4.0 (REST)
- **Admin UI**: EasyAdmin 4.x
- **Database**: Doctrine ORM 3.x / DBAL 4.x with MariaDB
- **Messaging**: Symfony Messenger (AMQP/RabbitMQ)
- **Auth**: OpenID Connect (`itk-dev/openid-connect-bundle`)
- **Frontend**: Webpack Encore, Stimulus.js
- **Testing**: PHPUnit 11+
- **Code Quality**: PHP-CS-Fixer, PHPStan, Rector

## Architecture

```mermaid
graph TD
A[Harvester] -->|POST DetectionResult| B[API Platform REST endpoint]
B --> C[Symfony Messenger]
C --> D[Async Message Handlers]
D --> D1[DirectoryHandler]
D --> D2[DockerImageHandler]
D --> D3[DrupalHandler]
D --> D4[GitHandler]
D --> D5[NginxHandler]
D --> D6[SymfonyHandler]
D1 & D2 & D3 & D4 & D5 & D6 --> E[Doctrine ORM]
E --> F[MariaDB]
F --> G[EasyAdmin UI]
```

### Key Directories

| Directory | Purpose |
|---|---|
| `src/Entity/` | ~20 Doctrine entities (Server, Site, Domain, Installation, Package, DockerImage, Advisory, etc.) |
| `src/Handler/` | DetectionResult handlers (Directory, Docker, Drupal, Git, Nginx, Symfony) |
| `src/MessageHandler/` | Async message processing (PersistDetectionResult, ProcessDetectionResult) |
| `src/Admin/` | EasyAdmin CRUD controllers |
| `src/ApiResource/` | API Platform resource definitions |
| `src/Service/` | Factories (PackageVersion, ModuleVersion, Advisory) and export services |
| `src/Repository/` | Doctrine repositories |
| `config/packages/` | Bundle configurations |
| `migrations/` | Doctrine migrations |
| `fixtures/` | Hautelook/Alice test fixtures |
| `tests/` | PHPUnit tests (Api, Controller, MessageHandler) |

### Data Flow

All analyzed data (sites, installations, domains, packages, etc.) can be
truncated and rebuilt by replaying DetectionResults. Manually maintained data
(Servers, OIDC setups, Service Certificates) is separate and must be preserved.

## Development Environment

```sh
# Start services (MariaDB, PHP-FPM 8.4, Nginx, Mailpit)
docker compose pull && docker compose up --detach

# Install dependencies
docker compose exec phpfpm composer install

# Run migrations
docker compose exec phpfpm bin/console doctrine:migrations:migrate --no-interaction

# Load fixtures
docker compose exec phpfpm composer fixtures

# Login as admin (after fixtures)
docker compose exec phpfpm bin/console itk-dev:openid-connect:login admin@example.com

# Process message queues
docker compose exec phpfpm composer queues

# Build frontend assets
docker compose run --rm node yarn install && docker compose run --rm node yarn build
```

## Quality Checks

All commands run inside Docker containers:

```sh
# PHP coding standards (PHP-CS-Fixer)
docker compose exec phpfpm composer coding-standards-check
docker compose exec phpfpm composer coding-standards-apply

# PHPUnit tests (creates test DB, runs migrations, executes tests)
docker compose exec phpfpm composer tests

# Frontend coding standards
docker compose run --rm node yarn coding-standards-check

# API spec export (must be committed)
docker compose exec phpfpm composer update-api-spec
```

## CI/CD

### GitHub Actions (`pr.yaml`)

Pull requests run these checks:

1. **Composer validation** - validates and installs (prod + dev)
2. **Doctrine schema validation** - migrations + schema check against MariaDB
3. **PHP-CS-Fixer** - coding standards
4. **PHPUnit** - unit/integration tests with MariaDB
5. **API spec validation** - ensures exported OpenAPI spec is up to date
6. **Fixtures** - verifies fixtures load successfully
7. **Asset build** - verifies frontend assets compile
8. **Changelog** - ensures CHANGELOG.md is updated

### Woodpecker CI (deployment)

- `stg.yml` - Deploys to staging on push to develop
- `prod.yml` - Deploys to production on release (Ansible playbook, runs migrations + transport setup)

## PR Guidelines

- PRs must link to a ticket
- Code must pass all CI checks (tests, coding standards, static analysis)
- CHANGELOG.md must be updated
- UI changes require screenshots
- Base branch: `develop`

## Important Conventions

- Entity classes extend `AbstractBaseEntity` (provides `id`, `createdAt`, `updatedAt`)
- Detection handlers implement `DetectionResultHandlerInterface`
- Handlers are auto-tagged and injected via tagged iterator in `services.yaml`
- Async processing uses Symfony Messenger with AMQP transport
- Environment-specific config goes in `.env.local` (not committed)
- API specs (`public/api-spec-v1.yaml` and `.json`) must be regenerated and committed when API changes
Loading