ci(autodoc): route Claude execution through ai-workflows to fix Bedrock OIDC - #36842
Conversation
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.
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
…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>
- Add modUser guardrail to the update path: fetch working inode before firing EDIT, skip with a clear log message if a human has an outstanding draft (live==false and modUser != CI Autodoc service account). Safe to proceed when live==true (no pending draft) or when the service account owns the working draft. - Move AUTODOC_DOTCMS_SITE_FOLDER from secrets.* to vars.* — non-sensitive config - Pass AUTODOC_DOTCMS_SITE_FOLDER as a with: input to the claude job Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… map - Pin actions/checkout (both instances) to 8ade135 # v4.2.2 - Pin actions/download-artifact to fa0a91b # v4.1.8 - Replace secrets: inherit on the claude job with an explicit map of only the three secrets autodoc-executor.yml actually declares, satisfying least-privilege (Semgrep secrets-inherit finding) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Not a credential — move from secrets.* to vars.* in both the executor with: block and the finalize job env, matching the AUTODOC_DOTCMS_SITE_FOLDER pattern already in place. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
b04fab0 to
28ed508
Compare
|
Flurry of activity above is just a rebase to resolve a conflict. I think this is the same branch as merged the autodoc automation in originally; if we'd cut a new branch, it would have avoided the need for this step. |
|
Claude finished @sfreudenthaler's task in 3m 26s —— View job Code ReviewFocused on the latest push (job restructure New Issues
Notes (non-blocking)
Resolved
· branch |
…uardrail Add permissions: id-token: write to the claude caller job so the reusable workflow can mint an OIDC token — GitHub intersects caller and callee permissions and id-token defaults to none without an explicit grant. Harden the modUser content check: use --fail-with-body and treat curl failures or unexpected responses as skip-with-warning rather than proceed, closing the fail-open path that could clobber a human draft. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Last push to attempts to fix the issues raised above. |
|
test-approval-check-ignore |
Should be good here. We dropped down to two secrets and moved the other one over to input in dotcms/ai-workflows#85 |
….yml GitHub Actions runs steps under bash -eo pipefail. CONTENT_CHECK=$(curl ...) is a bare assignment, so a failing curl aborts the script at that line under set -e — the following `if [ $? -ne 0 ]` guard was dead code and the intended graceful SKIP message never printed. Move the failure check onto the assignment itself with `if ! CONTENT_CHECK=$(...)`, which is set -e-safe. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUYRUem786kvJmTAdcY9F3
sfreudenthaler
left a comment
There was a problem hiding this comment.
LGTM. Fixed the set -e dead-code issue in the content-check curl guard (.github/workflows/issue_autodoc.yml:437-443) — moved the failure check onto the assignment itself with if ! CONTENT_CHECK=$(...) so the SKIP message actually fires on a failed curl instead of the step just going red before the guard runs.
relates to: dotCMS/ai-workflows#65
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
This PR fixes: #36949