Skip to content
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c7f884d
adding automation to automate documentation drafting
jdcmsd Jun 23, 2026
ccb1ca0
feat(autodoc): rewrite workflow to be self-contained (no uv)
jdcmsd Jun 23, 2026
bdbf60d
fix(autodoc): address code review findings in finalize step
jdcmsd Jun 24, 2026
4a9d387
fix(autodoc): address Bedrock review findings
jdcmsd Jun 24, 2026
a39ca6d
fix(autodoc): use AUTODOC_AIOS_CI for dotcms-aios checkout
jdcmsd Jun 24, 2026
6c176c5
chore(autodoc): drop git commit/push of report to dotcms-aios
jdcmsd Jun 24, 2026
295df69
refactor(autodoc): inline prompt; remove dotcms-aios autodoc/ dependency
jdcmsd Jun 24, 2026
da5f5a2
fix(autodoc): add source material quality check; restore details block
jdcmsd Jun 24, 2026
824f217
fix(autodoc): address code review — Epic type, Bedrock model, step split
jdcmsd Jun 26, 2026
78cedc9
ci(autodoc): replace AUTODOC_AIOS_CI PAT with CI_MACHINE_TOKEN for do…
jdcmsd Jun 26, 2026
0285403
ci(autodoc): route Claude execution through ai-workflows to fix Bedro…
jdcmsd Jul 31, 2026
3521c22
fix(autodoc): add modUser guardrail; move SITE_FOLDER to vars
jdcmsd Aug 3, 2026
cfe4658
fix(autodoc): pin action SHAs; replace secrets: inherit with explicit…
jdcmsd Aug 3, 2026
28ed508
fix: move AUTODOC_DOTCMS_BASE_URL from secrets to vars
jdcmsd Aug 4, 2026
d536809
ci: empty commit to re-trigger checks after GitHub outage
jdcmsd Aug 7, 2026
5ab4ba5
ci: re-trigger checks
jdcmsd Aug 7, 2026
13aad05
fix(autodoc): add id-token permission to claude job; harden modUser g…
jdcmsd Aug 7, 2026
2c7c92b
ci: re-trigger checks
jdcmsd Aug 7, 2026
47f9ee9
fix(ci): make content-check curl failure set -e-safe in issue_autodoc…
sfreudenthaler Aug 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
132 changes: 87 additions & 45 deletions .github/workflows/issue_autodoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
# needed), update (revise an existing page), or create (draft a new page).
# The report is posted as a comment on the issue, and update/create drafts
# are applied to the dotCMS documentation site through its content API.
#
# Job structure:
# preflight → prep → claude (via ai-workflows/autodoc-executor) → finalize
#
# The claude job uses dotCMS/ai-workflows as a reusable workflow so that the
# OIDC job_workflow_ref claim matches the trust condition on the
# GitHubActions-BedrockCodeReview IAM role. prep and finalize run directly
# in this workflow and do not touch AWS.
name: Autodoc — Epic Documentation Audit

on:
Expand Down Expand Up @@ -71,45 +79,33 @@ jobs:
echo "should_run=true" >> "$GITHUB_OUTPUT"
fi

autodoc:
name: Run documentation audit
prep:
name: Build evaluation context
needs: preflight
if: needs.preflight.outputs.should_run == 'true'
runs-on: ubuntu-latest
permissions:
issues: write
contents: read
id-token: write
issues: read
outputs:
eval_context: ${{ steps.ctx.outputs.content }}

env:
EPIC_NUMBER: ${{ github.event.issue.number }}
REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# Used by the Claude subprocess when it executes the curl in burlap.txt — not called directly here.
AUTODOC_DOTCMS_API_TOKEN_AISEARCH: ${{ secrets.AUTODOC_DOTCMS_API_TOKEN_AISEARCH }}
AUTODOC_DOTCMS_API_TOKEN_DRAFTING: ${{ secrets.AUTODOC_DOTCMS_API_TOKEN_DRAFTING }}
AUTODOC_DOTCMS_BASE_URL: ${{ secrets.AUTODOC_DOTCMS_BASE_URL }}
AUTODOC_DOTCMS_SITE_FOLDER: ${{ secrets.AUTODOC_DOTCMS_SITE_FOLDER }}

steps:
- name: Checkout triggering repo
uses: actions/checkout@v4
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.2.2

- name: Checkout dotcms-aios
uses: actions/checkout@v4
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.2.2
with:
repository: dotCMS/dotcms-aios
token: ${{ secrets.CI_MACHINE_TOKEN }}
path: dotcms-aios

- name: Configure AWS credentials (Bedrock)
if: vars.BEDROCK_ROLE_ARN != ''
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ vars.BEDROCK_ROLE_ARN }}
aws-region: ${{ vars.BEDROCK_AWS_REGION || 'us-east-1' }}

- name: Write prompt
run: |
cat > /tmp/burlap.txt << 'PROMPTEOF'
Expand Down Expand Up @@ -214,6 +210,7 @@ jobs:
PROMPTEOF

- name: Build eval context
id: ctx
run: |
cat > /tmp/ctx.py << 'PYEOF'
import json, os, subprocess, sys
Expand Down Expand Up @@ -297,7 +294,7 @@ jobs:
print(f'warning: no vault file for Epic #{epic_num}', file=sys.stderr)

prompt = open('/tmp/burlap.txt').read().strip()
report_path = f'/tmp/Epic-{epic_num}_burlap.md'
report_path = '/tmp/autodoc-report.md'
lines += [
'', '---', '', '## Prompt: burlap', '', prompt,
'', '---', '',
Expand All @@ -311,39 +308,57 @@ jobs:
PYEOF
python3 /tmp/ctx.py

- name: Load eval context
id: eval_context
run: |
{
echo 'content<<__AUTODOC_EOF__'
cat /tmp/eval_context.md
echo '__AUTODOC_EOF__'
} >> "$GITHUB_OUTPUT"

- name: Compose Claude args
id: claude_args
env:
BEDROCK_MODEL_ID: ${{ vars.BEDROCK_MODEL_ID }}
run: |
ARGS="--allowedTools Bash,Write"
if [ -n "$BEDROCK_MODEL_ID" ]; then
ARGS="--model $BEDROCK_MODEL_ID $ARGS"
fi
echo "value=$ARGS" >> "$GITHUB_OUTPUT"
claude:
name: Run Claude (Bedrock)
needs: prep
permissions:
id-token: write
contents: read
uses: dotCMS/ai-workflows/.github/workflows/autodoc-executor.yml@v3.5.0
secrets:
AUTODOC_DOTCMS_API_TOKEN_AISEARCH: ${{ secrets.AUTODOC_DOTCMS_API_TOKEN_AISEARCH }}
AUTODOC_DOTCMS_API_TOKEN_DRAFTING: ${{ secrets.AUTODOC_DOTCMS_API_TOKEN_DRAFTING }}
with:
prompt: ${{ needs.prep.outputs.eval_context }}
bedrock_role_arn: ${{ vars.BEDROCK_ROLE_ARN }}
model_id: ${{ vars.BEDROCK_MODEL_ID }}
autodoc_dotcms_site_folder: ${{ vars.AUTODOC_DOTCMS_SITE_FOLDER }}
autodoc_dotcms_base_url: ${{ vars.AUTODOC_DOTCMS_BASE_URL }}

finalize:
name: Post report and apply to dotCMS
needs: claude
if: always() && needs.claude.result != 'skipped'
runs-on: ubuntu-latest
permissions:
issues: write
contents: read

env:
EPIC_NUMBER: ${{ github.event.issue.number }}
REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AUTODOC_DOTCMS_API_TOKEN_DRAFTING: ${{ secrets.AUTODOC_DOTCMS_API_TOKEN_DRAFTING }}
AUTODOC_DOTCMS_BASE_URL: ${{ vars.AUTODOC_DOTCMS_BASE_URL }}
AUTODOC_DOTCMS_SITE_FOLDER: ${{ vars.AUTODOC_DOTCMS_SITE_FOLDER }}

- name: Run Claude
uses: anthropics/claude-code-action@v1
steps:
- name: Download report artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
use_bedrock: ${{ vars.BEDROCK_ROLE_ARN != '' && 'true' || 'false' }}
prompt: ${{ steps.eval_context.outputs.content }}
claude_args: ${{ steps.claude_args.outputs.value }}
use_sticky_comment: 'false'
track_progress: 'false'
name: autodoc-report
path: /tmp/
continue-on-error: true

- name: Post report comment
run: |
REPORT="/tmp/Epic-${EPIC_NUMBER}_burlap.md"
REPORT="/tmp/autodoc-report.md"

if [ ! -f "$REPORT" ]; then
echo "No report at $REPORT — skipping finalize."
Expand Down Expand Up @@ -391,7 +406,7 @@ jobs:
- name: Apply doc update to dotCMS
Comment thread
jdcmsd marked this conversation as resolved.
if: env.ACTION == 'update'
run: |
REPORT="/tmp/Epic-${EPIC_NUMBER}_burlap.md"
REPORT="/tmp/autodoc-report.md"

# Validate urlTitle is a URL slug before interpolating into the JSON query.
# Non-slug chars (quotes, backslashes) would break the shell-built JSON payload.
Expand All @@ -412,6 +427,34 @@ jobs:
exit 0
fi

# modUser guardrail: fetch the working inode and check whether it is safe
# to overwrite. GET /api/v1/content/{id} always returns the working inode.
#
# live==true → working IS the live version; no pending draft → safe.
# live==false → a draft exists on top of the published version.
# modUser == service account → automation owns the draft → safe.
# modUser == anyone else → human has an outstanding draft → skip.
if ! CONTENT_CHECK=$(curl -s --fail-with-body \
"$AUTODOC_DOTCMS_BASE_URL/api/v1/content/$IDENTIFIER" \
-H "Authorization: Bearer $AUTODOC_DOTCMS_API_TOKEN_DRAFTING"); then
echo "SKIP: content check request failed — cannot confirm draft ownership. Skipping to avoid clobbering a potential human edit."
exit 0
fi
IS_LIVE=$(echo "$CONTENT_CHECK" | jq -r '.entity.live // empty')
MOD_USER=$(echo "$CONTENT_CHECK" | jq -r '.entity.modUser // ""')
SERVICE_ACCOUNT='user-3244a6be-d28b-4d80-a3fc-9f66a1d832ae'

if [ -z "$IS_LIVE" ]; then
echo "SKIP: content check returned unexpected response — cannot confirm draft ownership. Skipping to avoid clobbering a potential human edit."
exit 0
fi

if [ "$IS_LIVE" = "false" ] && [ "$MOD_USER" != "$SERVICE_ACCOUNT" ]; then
echo "SKIP: outstanding draft last saved by '${MOD_USER}' (not the CI Autodoc service account)."
echo "The automation will not overwrite a human edit. Please review the draft in dotCMS and apply the proposed changes manually if appropriate."
exit 0
fi

export REPORT IDENTIFIER
python3 << 'PYEOF'
import json, os
Expand All @@ -434,7 +477,7 @@ jobs:
- name: Apply doc create to dotCMS
if: env.ACTION == 'create'
run: |
REPORT="/tmp/Epic-${EPIC_NUMBER}_burlap.md"
REPORT="/tmp/autodoc-report.md"

# Validate urlTitle is a URL slug before interpolating into the JSON query.
if ! echo "$URL_TITLE" | grep -qE '^[a-z0-9][a-z0-9-]*[a-z0-9]$'; then
Expand Down Expand Up @@ -470,4 +513,3 @@ jobs:
-H "Authorization: Bearer $AUTODOC_DOTCMS_API_TOKEN_DRAFTING" \
-H "Content-Type: application/json" \
--data @/tmp/payload.json

Loading