Skip to content

fix(deps): resolve high and critical npm advisories (SEC-213) #224

fix(deps): resolve high and critical npm advisories (SEC-213)

fix(deps): resolve high and critical npm advisories (SEC-213) #224

Workflow file for this run

name: Docs Draft PR
# Publishes a drafted docs update (produced by `docs-drift-check.yml`) as a
# draft PR in the centralized docs repo. Triggered only by a `/publish-docs-pr`
# chatops comment from a trusted contributor on a PR in this repo.
#
# Required secrets:
# CLAUDE_CODE_OAUTH_TOKEN
# DOCS_REPO_TOKEN — fine-grained PAT or GitHub App token with
# contents:write + pull_requests:write on relayprotocol/relay-docs
on:
issue_comment:
types: [created]
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
jobs:
docs-draft-pr:
if: >
github.event_name == 'issue_comment'
&& github.event.issue.pull_request != null
&& startsWith(github.event.comment.body, '/publish-docs-pr')
&& (
github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR'
)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
steps:
- name: Acknowledge command
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.issue.number }}
ACTOR: ${{ github.event.comment.user.login }}
DOCS_REPO: relayprotocol/relay-docs
run: |
gh api -X POST \
"repos/${{ github.repository }}/issues/${PR_NUMBER}/reactions" \
-f content='eyes' >/dev/null || true
gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body \
"🚚 **Docs Draft PR** — starting publish to \`${DOCS_REPO}\`, requested by @${ACTOR}. I'll post the PR link here when it's ready."
- name: Checkout calling repo workspace
# We need *some* workspace for Claude's Read/Glob/Write tools. A minimal
# checkout of the calling repo gives Claude a valid workspace to operate
# in. The actual docs editing happens inside the _docs-repo clone below.
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: ${{ github.repository }}
fetch-depth: 1
- name: Fetch latest drift-check draft from PR
id: fetch-draft
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
# Grab the latest "Docs Drift Check" sticky comment from this PR.
# That comment contains the drafted MDX, file paths, and confidence.
COMMENT=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
--jq '[.[] | select(.user.login == "github-actions[bot]") | select(.body | contains("Docs Drift Check"))] | last | .body // ""')
if [ -z "$COMMENT" ]; then
gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body \
"⚠️ **Docs Draft PR** — no drift-check comment found on this PR. The drift-check workflow must complete before publishing. Re-run it or push a commit to trigger it, then retry \`/publish-docs-pr\`."
exit 1
fi
# Refuse to publish if the drift check said "no docs impact" or was below floor.
if echo "$COMMENT" | grep -q "No docs impact"; then
gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body \
"🛑 **Docs Draft PR** — the latest drift check concluded this PR has no docs impact. Nothing to publish. If you disagree, open an issue manually in \`relayprotocol/relay-docs\`."
exit 1
fi
if echo "$COMMENT" | grep -q "Confidence: LOW"; then
gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body \
"🛑 **Docs Draft PR** — the latest drift check was LOW confidence and deliberately did not draft content. Please open an issue manually in \`relayprotocol/relay-docs\` describing the change rather than auto-publishing a low-confidence draft."
exit 1
fi
# Persist the comment body inside the workspace so Claude's Read tool can see it.
mkdir -p _drift
printf '%s' "$COMMENT" > "_drift/drift_comment.md"
echo "comment_path=_drift/drift_comment.md" >> "$GITHUB_OUTPUT"
- name: Fetch source PR metadata
id: pr-meta
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
mkdir -p _drift
gh pr view "$PR_NUMBER" --json number,title,author,url,headRefOid \
> "_drift/pr_meta.json"
echo "meta_path=_drift/pr_meta.json" >> "$GITHUB_OUTPUT"
- name: Clone docs repo with write token
env:
DOCS_REPO_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }}
DOCS_REPO: relayprotocol/relay-docs
DOCS_BASE_REF: main
PR_NUMBER: ${{ github.event.issue.number }}
PR_META_PATH: ${{ steps.pr-meta.outputs.meta_path }}
run: |
# issue_comment events don't include PR head SHA in the payload,
# so read it from the metadata we just fetched with `gh pr view`.
SOURCE_SHA=$(jq -r '.headRefOid' < "$PR_META_PATH")
SHORT_SHA="${SOURCE_SHA:0:7}"
SOURCE_REPO_SLUG="${GITHUB_REPOSITORY//\//-}"
git clone --branch "$DOCS_BASE_REF" \
"https://x-access-token:${DOCS_REPO_TOKEN}@github.com/${DOCS_REPO}.git" \
"_docs-repo"
cd "_docs-repo"
git config user.name "relay-docs-bot"
git config user.email "relay-docs-bot@users.noreply.github.com"
# Unique branch per source PR + short SHA so retries are idempotent.
BRANCH="docs-drift/${SOURCE_REPO_SLUG}-pr-${PR_NUMBER}-${SHORT_SHA}"
echo "branch=$BRANCH" >> "$GITHUB_ENV"
git checkout -B "$BRANCH"
echo "DOCS_REPO_PATH=_docs-repo" >> "$GITHUB_ENV"
- name: Write draft files with Claude
id: write-draft
uses: anthropics/claude-code-action@1298632ce7736903d02a1435002705aa2a594a6c # v1
with:
github_token: ${{ github.token }}
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
track_progress: true
show_full_output: true
# Read/Glob/Grep to inspect the draft and the docs repo, Write/Edit
# to materialize file changes. No Bash — the runner handles commit,
# push, and PR creation in a later step with the scoped PAT.
claude_args: '--model opus --max-turns 40 --allowedTools "Read,Glob,Grep,Write,Edit"'
prompt: |
You are **Relay Docs Publisher** — an automated editor that takes a
previously-drafted docs update and materializes it as real file
changes inside the cloned docs repo.
Inputs available on disk:
- Drift-check comment body: `${{ steps.fetch-draft.outputs.comment_path }}`
- Source PR metadata (JSON): `${{ steps.pr-meta.outputs.meta_path }}`
- Docs repo clone root: `${{ env.DOCS_REPO_PATH }}`
- Docs repo style guide: `${{ env.DOCS_REPO_PATH }}/CLAUDE.md`
CRITICAL TOOL CONSTRAINTS:
- Use `Read` to read files. Use `Write` to create new files. Use `Edit` to modify existing files.
- Bash is restricted to read-only operations on the already-cloned docs repo. Do NOT push, commit, or create PRs — a later step does that.
- Do NOT invent content. Everything you write must come from the drift-check comment, optionally reconciled with the docs style guide.
## Step 1: Load the draft
1. `Read` the drift-check comment at `${{ steps.fetch-draft.outputs.comment_path }}`.
2. Identify every fenced code block that begins with
````mdx path=<target-path> action=<create|update>````
These are the file-level instructions.
3. `Read` `${{ env.DOCS_REPO_PATH }}/CLAUDE.md` to refresh the style rules.
## Step 2: Materialize each change
For each fenced block in the draft comment:
- If `action=create`: `Write` the file at `${{ env.DOCS_REPO_PATH }}/<target-path>` with the block's contents as the full file body. Ensure frontmatter and heading levels conform to the style guide.
- If `action=update`: `Read` the existing file at `${{ env.DOCS_REPO_PATH }}/<target-path>`. Apply the `> Replace section:` / `> Insert after:` directive from the block precisely. Use `Edit` for surgical changes — never rewrite unaffected sections.
If a fenced block's target path does not exist and `action=update`, treat it as `create` and note this in your final summary.
Do NOT create or edit any file outside the paths declared in the draft.
## Step 3: Verify style-guide conformance
For every file you wrote or edited:
- Frontmatter present with `title` and `description`.
- No `#` (H1) in the body — the frontmatter title is H1.
- Heading levels do not skip (no `##` directly to `####`).
- MDX components used correctly: `<Tip>`, `<Warning>`, `<Info>`, `<Note>` under 15 rendered lines each.
- Internal links use root-relative paths (`/features/...`), not relative or absolute URLs.
Fix any violations in place. If a violation cannot be fixed without
inventing content, leave the offending section as-is and record the
issue in the final summary.
## Step 4: Emit a summary
When done, print (as your final message) a block like:
```
DOCS_PUBLISH_SUMMARY_START
branch: <nothing here — the runner already set it>
files_changed:
- path: references/.../file.mdx
action: create | update
notes:
- <any deviations, skipped sections, or flags for human reviewer>
DOCS_PUBLISH_SUMMARY_END
```
Do NOT attempt to commit, push, or open a PR. The runner does that
in the next step using a scoped token.
- name: Commit, push, and open draft PR
id: open-pr
env:
GH_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }}
DOCS_REPO: relayprotocol/relay-docs
DOCS_BASE_REF: main
SOURCE_REPO: ${{ github.repository }}
SOURCE_PR_NUMBER: ${{ github.event.issue.number }}
SOURCE_PR_URL: ${{ github.event.issue.html_url }}
ACTOR: ${{ github.event.comment.user.login }}
BRANCH: ${{ env.branch }}
DOCS_REPO_PATH: ${{ env.DOCS_REPO_PATH }}
run: |
cd "$DOCS_REPO_PATH"
# Stage first so both tracked and new files count toward the change check.
git add -A
if git diff --cached --quiet; then
gh pr comment "$SOURCE_PR_NUMBER" --repo "$SOURCE_REPO" --body \
"🛑 **Docs Draft PR** — Claude produced no file changes. Nothing to publish. Check the drift-check comment for malformed or missing fenced blocks."
exit 1
fi
git commit -m "docs(drift): draft from ${SOURCE_REPO}#${SOURCE_PR_NUMBER}" \
-m "Requested by @${ACTOR} via /publish-docs-pr on ${SOURCE_PR_URL}"
git push -u origin "$BRANCH"
PR_BODY=$(cat <<EOF
Drafted from [${SOURCE_REPO}#${SOURCE_PR_NUMBER}](${SOURCE_PR_URL}), requested by @${ACTOR}.
This PR was auto-generated by the \`docs-draft-pr\` workflow from a Claude-drafted update in the source repo. It is opened as a **draft** — please review, edit as needed, and mark ready for review before merging.
**Review checklist**
- [ ] Content matches the behavior shipped in the source PR
- [ ] No internal-only details (service names, file paths, unreleased names, security internals) leaked into the draft
- [ ] Conforms to \`CLAUDE.md\` style rules
- [ ] Cross-references and internal links resolve
- [ ] Any \`Needs human input\` items from the source comment are addressed
---
_Generated by \`docs-draft-pr.yml\` in \`${SOURCE_REPO}\`._
EOF
)
PR_URL=$(gh pr create \
--repo "$DOCS_REPO" \
--base "$DOCS_BASE_REF" \
--head "$BRANCH" \
--title "docs(drift): draft from ${SOURCE_REPO}#${SOURCE_PR_NUMBER}" \
--body "$PR_BODY" \
--draft \
--assignee "$ACTOR" 2>/dev/null || true)
# If --assignee failed (actor is not a docs-repo collaborator), retry without it.
if [ -z "$PR_URL" ]; then
PR_URL=$(gh pr create \
--repo "$DOCS_REPO" \
--base "$DOCS_BASE_REF" \
--head "$BRANCH" \
--title "docs(drift): draft from ${SOURCE_REPO}#${SOURCE_PR_NUMBER}" \
--body "$PR_BODY" \
--draft)
fi
echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT"
- name: Comment PR link back on source PR
if: steps.open-pr.outputs.pr_url != ''
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.issue.number }}
DOCS_PR_URL: ${{ steps.open-pr.outputs.pr_url }}
ACTOR: ${{ github.event.comment.user.login }}
run: |
gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body \
"✅ **Docs Draft PR** opened: ${DOCS_PR_URL}
@${ACTOR} is assigned on the draft PR. Review and mark ready when it's good."
- name: Comment failure back on source PR
if: failure()
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.issue.number }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
gh pr comment "$PR_NUMBER" --repo "${{ github.repository }}" --body \
"❌ **Docs Draft PR** failed. See the workflow run: ${RUN_URL}"