ci(autodoc): route Claude execution through ai-workflows to fix Bedrock OIDC - #36842
ci(autodoc): route Claude execution through ai-workflows to fix Bedrock OIDC#36842jdcmsd wants to merge 15 commits into
Conversation
Replace uv/Python-script-based eval and finalize steps with: - Python3 stdlib context assembly using gh CLI and grep - Shell finalize using gh issue comment, curl for dotCMS API, and git commit/push - prompts/burlap.txt read directly via cat (no YAML parsing) - Fix jq null parent bug in preflight guard Eliminates dependency on dotcms-aios PR merge order.
- Fix -f → -F on gh api PATCH so the file is read, not sent literally - Prepend <!-- autodoc-report --> marker in finalize before posting so idempotent edit lookup works (marker was not in the report itself) - Add --paginate to comment lookup to search beyond the first page - Use jq first // empty instead of | head -1 to avoid SIGPIPE - Fix urlTitle awk to use sub() consistent with title/tags/seoDescription - Remove -k (TLS bypass); add --fail-with-body to dotCMS curl calls - Add comment clarifying AUTODOC_DOTCMS_API_TOKEN_AISEARCH is used by the Claude subprocess via burlap.txt, not directly by a workflow step
- Make git push conditional on commit succeeding (|| true was causing unconditional push even when there was nothing new to commit) - Add git push origin HEAD for explicit branch targeting - Validate urlTitle is a URL slug before interpolating into JSON query (non-slug chars would break the shell-built -d payload) - Validate IDENTIFIER matches UUID format before placing in URL - Add comment on unpinned npm install explaining the tradeoff
Report lives as an issue comment — the repo copy is redundant. Removing the push also drops the write-scope requirement on AUTODOC_AIOS_CI.
Embed burlap.txt content directly in the workflow as a heredoc step. Update report path to /tmp — report is ephemeral, lives as issue comment. dotcms-aios checkout now solely serves vault epic context lookup.
- Add conservatism clause to prompt: if Epic lacks technical detail, set action none rather than hallucinating a draft - Restore <details> wrapping of doc draft in issue comment (was lost when post_report.py was replaced with inline shell)
- Replace label check for Epic with issue type check (github.event.issue.type.name)
- Update GraphQL parent lookup to use issueType { name } instead of labels
- Add id-token: write permission for Bedrock OIDC
- Replace npm install + claude --print with anthropics/claude-code-action@v1;
model and Bedrock role sourced from vars.BEDROCK_MODEL_ID / vars.BEDROCK_ROLE_ARN
- Split finalize into three discrete steps for easier auditing:
Post report comment / Apply doc update to dotCMS / Apply doc create to dotCMS
…log; not worth its own PR.
…tcms-aios checkout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ck OIDC Restructures the autodoc job into prep → claude → finalize so that the Claude/Bedrock step runs inside dotCMS/ai-workflows/autodoc-executor.yml. This sets job_workflow_ref to the ai-workflows ref, satisfying the trust condition on GitHubActions-BedrockCodeReview that was blocking OIDC assumption. The claude job references autodoc-executor.yml@v3.5.0 — pending the next ai-workflows release after dotCMS/ai-workflows#<PR> merges. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sfreudenthaler
left a comment
There was a problem hiding this comment.
These look good overall — nice work routing through ai-workflows to fix the OIDC trust issue, and the finalize step follows the same draft-then-apply pattern we landed for the changelog site publisher. Two things before this is ready to merge:
-
No human-edit guardrail on the update path (see inline comment below). My changelog publisher checks
modUseron the existing content and skips (with a visible skip marker) if the last edit wasn't made by the service account, specifically so the automation never clobbers a manual edit made in the dotCMS backend. This workflow's "Apply doc update to dotCMS" step has no equivalent check — it will overwrite thedocumentationfield unconditionally, and there's no log line or alert anywhere that would tell us it happened. Given Jamie (or anyone) could be hand-editing these pages between Epic closures, I'd want that guardrail before this runs against real content. -
Publish-gate question (also inline below): my changelog automation auto-publishes with no approval gate, but that's safe because the content is deterministic — the GitHub release body IS the site content, mechanically transformed. Here Claude is generating original documentation prose, so there's real hallucination risk. Before this merges I want to confirm what
AUTODOC_DOTCMS_BASE_URLpoints at and what the defaultEDIT/NEWworkflow actions actually do on theDotcmsDocumentationcontent type — does firing them here land the page in Draft/Review, or does it go straight to Published with no human in the loop? If it's the latter, we need either a review gate before publish, or to restrict this to a staging/review instance until there's human sign-off on the draft.
| echo "ACTION=${ACTION:-none}" >> "$GITHUB_ENV" | ||
| echo "URL_TITLE=$URL_TITLE" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Apply doc update to dotCMS |
There was a problem hiding this comment.
No guardrail here against overwriting a human edit. My changelog publisher reads modUser on the existing contentlet first and skips (logging a skip marker) if the last editor wasn't the service account — that's what stops it from clobbering someone's manual change. This step fires straight to the API with the LLM's draft regardless of who last touched the page, and nothing here would log or alert if that happens. Want the same modUser check added before this goes live against real content.
| PYEOF | ||
|
|
||
| curl -s --fail-with-body -X PUT \ | ||
| "$AUTODOC_DOTCMS_BASE_URL/api/v1/workflow/actions/default/fire/EDIT?identifier=$IDENTIFIER" \ |
There was a problem hiding this comment.
This publishes unconditionally once ACTION == update. Unlike the changelog publisher (deterministic content, so safe to auto-publish with no gate), this content is LLM-generated — real hallucination risk. Need to confirm: what does AUTODOC_DOTCMS_BASE_URL point at, and does firing the default EDIT action here actually leave the page in Draft/Review, or does it go straight to Published? If the latter, this needs a review/approval step before anything hits live docs.
Summary
autodocjob intoprep → claude → finalizeso Claude/Bedrock runs insidedotCMS/ai-workflows/autodoc-executor.ymljob_workflow_refto theai-workflowsref, satisfying the trust condition onGitHubActions-BedrockCodeReviewthat was blocking OIDC assumption withNot authorized to perform sts:AssumeRoleWithWebIdentityprepandfinalizejobs run directly in this workflow and do not touch AWS/tmp/autodoc-report.md; passed between jobs via Actions artifactRoot cause
The IAM role's trust policy requires
job_workflow_refto matchdotCMS/ai-workflows/.github/workflows/*@refs/tags/*. When the Claude step ran directly insideissue_autodoc.yml,job_workflow_refwasdotCMS/core/.github/workflows/issue_autodoc.yml@...— a hard deny. Routing through theai-workflowsreusable workflow fixes the claim.Dependency
Merge
dotCMS/ai-workflows#65and tagv3.5.0before merging this PR. Theclaudejob referencesautodoc-executor.yml@v3.5.0.Test plan
dotCMS/ai-workflows#65is merged and taggedv3.5.0🤖 Generated with Claude Code