feat(dot-browser-selector): add Upload New File button to File Picker in New Edit Content #396
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Claude Backend Code Reviewer | |
| # Pilot: runs only on PRs from developers listed in the authorized-authors job. | |
| # To expand: add logins to PILOT_AUTHORS or replace with a team membership check. | |
| on: | |
| pull_request: | |
| types: [opened, synchronize] | |
| jobs: | |
| # ───────────────────────────────────────────────────────────────── | |
| # Gate 1 — Pilot author allowlist | |
| # ───────────────────────────────────────────────────────────────── | |
| authorized-authors: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| authorized: ${{ steps.check.outputs.authorized }} | |
| steps: | |
| - name: Check if PR author is in pilot list | |
| id: check | |
| env: | |
| AUTHOR: ${{ github.event.pull_request.user.login }} | |
| run: | | |
| PILOT_AUTHORS='["dsolistorres","gortiz-dotcms","dsilvam"]' | |
| if echo "$PILOT_AUTHORS" | jq -e --arg a "$AUTHOR" 'index($a) != null' > /dev/null; then | |
| echo "authorized=true" >> $GITHUB_OUTPUT | |
| echo "✅ $AUTHOR is in the pilot list" | |
| else | |
| echo "authorized=false" >> $GITHUB_OUTPUT | |
| echo "ℹ️ $AUTHOR is not in the pilot list — skipping backend review" | |
| fi | |
| # ───────────────────────────────────────────────────────────────── | |
| # Gate 2 — Detect Java file changes | |
| # Skips entirely if no .java files changed — saves API cost. | |
| # ───────────────────────────────────────────────────────────────── | |
| detect-backend-changes: | |
| needs: authorized-authors | |
| if: needs.authorized-authors.outputs.authorized == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| has_java: ${{ steps.check.outputs.has_java }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for Java file changes | |
| id: check | |
| env: | |
| BASE_REF: ${{ github.base_ref }} | |
| run: | | |
| CHANGED=$(git diff --name-only "origin/${BASE_REF}...HEAD") | |
| echo "Changed files:" | |
| echo "$CHANGED" | |
| if echo "$CHANGED" | grep -qE '\.java$'; then | |
| echo "has_java=true" >> $GITHUB_OUTPUT | |
| echo "✅ Java files detected — proceeding with backend review" | |
| else | |
| echo "has_java=false" >> $GITHUB_OUTPUT | |
| echo "ℹ️ No Java files changed — skipping backend review" | |
| fi | |
| # ───────────────────────────────────────────────────────────────── | |
| # Backend review — multi-agent orchestrator | |
| # | |
| # Spawns 4 specialized sub-agents in parallel (security, database, | |
| # java-standards, rest-api), collects findings, deduplicates, and | |
| # posts a single structured comment on the PR. | |
| # ───────────────────────────────────────────────────────────────── | |
| claude-backend-review: | |
| needs: [authorized-authors, detect-backend-changes] | |
| if: | | |
| needs.authorized-authors.outputs.authorized == 'true' && | |
| needs.detect-backend-changes.outputs.has_java == 'true' | |
| concurrency: | |
| group: claude-backend-review-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: write | |
| id-token: write | |
| pull-requests: write | |
| issues: write | |
| uses: dotCMS/ai-workflows/.github/workflows/claude-orchestrator.yml@v2.0.0 | |
| with: | |
| trigger_mode: automatic | |
| timeout_minutes: 30 | |
| runner: ubuntu-latest | |
| enable_mention_detection: false | |
| claude_args: >- | |
| --allowedTools | |
| "Agent,Bash(git diff*),Bash(git log*),Bash(git show*),Bash(cat CLAUDE.md*),Bash(cat docs/backend/*),Bash(cat docs/core/*),Bash(cat dotCMS/src/*),Bash(find dotCMS/src -name '*.java'*),Bash(grep -rn dotCMS/src*),Bash(gh pr comment*),Bash(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments*),Bash(gh api repos/${{ github.repository }}/issues/comments/*),Bash(jq*)" | |
| prompt: | | |
| You are the orchestrator of a dotCMS backend code review pipeline. | |
| Your job is to coordinate specialized sub-agents, collect their findings, | |
| and post one consolidated review comment on the PR. | |
| ## STEP 1 — Load dotCMS conventions | |
| Read these files before doing anything else: | |
| cat CLAUDE.md | |
| cat docs/backend/JAVA_STANDARDS.md | |
| cat docs/backend/DATABASE_PATTERNS.md | |
| cat docs/backend/REST_API_PATTERNS.md | |
| cat docs/core/SECURITY_PRINCIPLES.md | |
| ## STEP 2 — Get the Java diff | |
| git diff ${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }} -- '*.java' | |
| ## STEP 3 — Spawn 4 specialized sub-agents in parallel | |
| Use the Agent tool to launch all four sub-agents at the same time. | |
| Pass each sub-agent the full diff output from STEP 2 and the relevant | |
| rules from the docs you read in STEP 1. | |
| --- | |
| ### Sub-agent 1: Security Reviewer | |
| Focus exclusively on security issues: | |
| - Permission checks missing before accessing or modifying content/users | |
| (look for missing DotSecurityException or hasPermission calls) | |
| - SQL built with string concatenation — must use DotConnect + addParam() | |
| - User input used in file paths or system calls without validation | |
| - Sensitive data (tokens, passwords, PII) logged via Logger or returned in responses | |
| - Hardcoded secrets, API keys, or environment-specific values | |
| - System.getProperty / System.getenv — must use Config.getStringProperty() | |
| Investigate beyond the diff when needed: | |
| - If a method takes user input, read the full method to see how it's used | |
| - grep -rn for usages of a modified security-sensitive method | |
| Return findings as a markdown list. Each finding must include: | |
| - Severity: 🔴 Critical / 🟠 High / 🟡 Medium | |
| - File path and line number | |
| - What the problem is and why it matters | |
| - The problematic code snippet (2-4 lines max) | |
| - Suggested fix if straightforward | |
| If no security issues found, return: NO_FINDINGS | |
| --- | |
| ### Sub-agent 2: Database Reviewer | |
| Focus exclusively on database and cache issues: | |
| - SQL built with string concatenation — must use DotConnect + addParam() | |
| - Multi-step writes without LocalTransaction.wrapReturn() or @WrapInTransaction | |
| - Hibernate session used where DotConnect should be used | |
| - SELECT * in production queries | |
| - Write or delete operations that don't invalidate the relevant CacheLocator entry | |
| - Missing @WrapInTransaction on API methods that write to the DB | |
| Investigate beyond the diff when needed: | |
| - If a write operation is added, read surrounding code to check for transaction scope | |
| - grep -rn for the modified class in CacheLocator to check existing cache patterns | |
| Return findings in the same format as Sub-agent 1. | |
| If no database issues found, return: NO_FINDINGS | |
| --- | |
| ### Sub-agent 3: Java Standards Reviewer | |
| Focus exclusively on Java syntax and code quality: | |
| - Java 21+ syntax in core modules (text blocks, records, switch expressions) | |
| — Java 11 syntax only, EXCEPT in tools/dotcms-cli | |
| - Raw types: List, Map, Set without generics | |
| - Missing @Override on methods that override a parent | |
| - System.out.println — must use Logger.info/error/debug(this, msg) | |
| - System.getProperty / System.getenv — must use Config.getStringProperty() | |
| - Direct instantiation of API or Factory classes — must use APILocator or FactoryLocator | |
| - WebAPILocator used outside REST resources or servlets | |
| - New dependencies added directly to dotCMS/pom.xml instead of bom/application/pom.xml | |
| Return findings in the same format as Sub-agent 1. | |
| If no Java standard issues found, return: NO_FINDINGS | |
| --- | |
| ### Sub-agent 4: REST API Reviewer | |
| Focus exclusively on REST API issues: | |
| - @Schema annotation absent or type doesn't match the actual return type | |
| - Exceptions caught silently (empty catch blocks, exception not mapped to HTTP response) | |
| - Missing UtilMethods.isSet() validation on path or query params | |
| - Missing webResource.init() call at the start of endpoint methods | |
| - Missing @NoCache on read endpoints | |
| - Error messages that expose internal stack traces or system details to the caller | |
| Investigate beyond the diff when needed: | |
| - Read the full resource class if only part of it changed | |
| - Check sibling endpoint methods for consistent error handling patterns | |
| Return findings in the same format as Sub-agent 1. | |
| If no REST API issues found, return: NO_FINDINGS | |
| --- | |
| ## STEP 4 — Consolidate findings | |
| Once all sub-agents return: | |
| 1. Collect all findings from the four sub-agents | |
| 2. Remove exact duplicates (same file + line flagged by two agents — keep the higher severity) | |
| 3. Sort by severity: 🔴 Critical first, then 🟠 High, then 🟡 Medium | |
| 4. If ALL four sub-agents returned NO_FINDINGS, the review is clean | |
| 5. If a sub-agent errored, returned empty output, or returned unparseable content, | |
| do NOT treat it as NO_FINDINGS. Instead include a warning in the comment: | |
| ⚠️ **<Domain> review unavailable** — sub-agent failed, manual review required for this area. | |
| ## STEP 5 — Post a single PR comment | |
| Write the full review body to a temp file, then post it with --body-file. | |
| This avoids any risk of shell injection from delimiter collisions. | |
| Write findings to /tmp/dotcms_review_body.md using this format. | |
| The FIRST LINE must always be exactly: <!-- dotcms-backend-review --> | |
| This marker is invisible in GitHub's rendered markdown and is used to find | |
| and update this specific comment on future pushes without touching any other | |
| bot comment on the PR. | |
| <!-- dotcms-backend-review --> | |
| ## 🔍 dotCMS Backend Review | |
| <one block per issue> | |
| **[🔴 Critical / 🟠 High / 🟡 Medium]** `path/to/File.java:LINE` | |
| > What the problem is and why it matters in the dotCMS context. | |
| ```java | |
| // problematic code snippet (2-4 lines) | |
| ``` | |
| 💡 _Suggested fix (only if straightforward)_ | |
| --- | |
| **Next steps** | |
| - 🔴 / 🟠 Fix locally and push — these need your judgment | |
| - 🟡 You can ask me to handle mechanical fixes inline: `@claude fix <issue description> in <File.java>` | |
| - Every new push triggers a fresh review automatically | |
| Then post it using the marker to find and update the existing review comment, | |
| or create a new one if none exists yet: | |
| COMMENT_ID=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments \ | |
| --jq '[.[] | select(.body | startswith("<!-- dotcms-backend-review -->"))] | last | .id // empty') | |
| if [ -n "$COMMENT_ID" ]; then | |
| jq -n --rawfile body /tmp/dotcms_review_body.md '{"body": $body}' \ | |
| | gh api repos/${{ github.repository }}/issues/comments/$COMMENT_ID -X PATCH --input - | |
| else | |
| gh pr comment ${{ github.event.pull_request.number }} --body-file /tmp/dotcms_review_body.md | |
| fi | |
| If ALL agents returned NO_FINDINGS, write this to /tmp/dotcms_review_body.md instead: | |
| <!-- dotcms-backend-review --> | |
| ✅ **dotCMS Backend Review**: no issues found. | |
| Then follow the same find-and-update-or-create logic above. | |
| Rules: | |
| - One block per issue — do not combine multiple issues | |
| - Be specific: quote actual file names and line numbers | |
| - Do not praise. Do not summarize what the PR does. | |
| - Do not invent issues. Only report what sub-agents confirmed. | |
| secrets: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} |