Skip to content

test: trigger GitHub Actions#3

Merged
ishwar-prog merged 9 commits into
mainfrom
test/actions-trigger
May 1, 2026
Merged

test: trigger GitHub Actions#3
ishwar-prog merged 9 commits into
mainfrom
test/actions-trigger

Conversation

@ishwar-prog
Copy link
Copy Markdown
Owner

@ishwar-prog ishwar-prog commented May 1, 2026

Summary by CodeRabbit

  • New Features

    • DocSync GitHub Action added to detect documentation drift on PRs and pushes, report drift score, list affected files, and optionally generate AI-backed docs and create companion PRs.
  • Chores

    • New CI workflow to lint, test, and validate the action.
    • Automation workflow to run DocSync on PR events and pushes, post results, and expose companion PR info.
  • Quality

    • Linting configuration and runtime dependency updates added.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

Warning

Rate limit exceeded

@ishwar-prog has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 4 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bcf2d812-dfee-4107-addd-f5ec50705b78

📥 Commits

Reviewing files that changed from the base of the PR and between 92089f8 and a2e973a.

📒 Files selected for processing (12)
  • .github/workflows/ci.yml
  • src/action/push-handler.js
  • src/commands/check.js
  • src/commands/fix.js
  • src/commands/init.js
  • src/core/drift.js
  • src/core/generator.js
  • src/core/parser.js
  • src/github/client.js
  • src/github/pr-processor.js
  • src/github/webhook-server.js
  • src/utils/logger.js
📝 Walkthrough

Walkthrough

Adds DocSync GitHub Action, related workflows, and runtime code to detect documentation drift for JS/TS repos, compare PR changes to a snapshot, optionally generate AI-backed docs, create companion PRs/comments, and update snapshots on default-branch pushes.

Changes

Cohort / File(s) Summary
Workflows
\.github/workflows/ci.yml, \.github/workflows/docsync.yml
Add CI workflow (lint/test, action validation, self-check run) and a DocSync workflow that runs on PR events and pushes to main/master to perform drift detection, allow companion PR creation, and echo drift outputs.
Action manifest & deps
action.yml, package.json
New GitHub Action manifest defining inputs/outputs and Node20 entrypoint; adds @actions/core, @actions/exec, and @actions/github to runtime dependencies.
Action runtime
src/action/index.js
Main entrypoint: read/validate inputs, mask secrets, set env/logging, create Octokit, dispatch events to PR or push handlers with error handling.
PR handler
src/action/pr-handler.js
New handlePullRequest export: paginate PR files, filter/download JS/TS files, load baseline snapshot, parse/compute drift, branch flows (in-sync, below-threshold, drift), optionally generate AI docs, create companion PR, post comments, and write summaries.
Push handler
src/action/push-handler.js
New handlePush export: ensure default-branch push, scan/parse trackable files, analyze drift vs snapshot when present, write job summary, and save updated snapshot.
Reporting & logging
src/action/reporter.js, src/utils/logger.js
Add reporter.writeSummary(...) to compose Actions job summaries (drift bar, affected files, AI generation summary, companion PR link) and logBanner(text) utility for console banners.
Config & lint
src/utils/config.js, eslint.config.cjs
loadConfig gains configFilename parameter (defaults to docsync.yaml); new ESLint config exporting recommended JS rules with Node globals marked readonly.

Sequence Diagram(s)

sequenceDiagram
    participant GH as GitHub Actions
    participant Action as DocSync Action
    participant API as GitHub API
    participant Parser as File Parser
    participant AI as AI Service
    participant FS as File System

    GH->>Action: Trigger on pull_request / pull_request_target
    Action->>API: List PR files (paginated)
    API-->>Action: Changed file list
    Action->>FS: Download selected JS/TS files
    FS-->>Action: Files available
    Action->>FS: Load baseline snapshot
    FS-->>Action: Snapshot data
    Action->>Parser: Parse files -> constructs
    Parser-->>Action: Parsed structures
    Action->>Action: analyzeDrift(baseline, current)
    alt Drift exceeds threshold
        Action->>AI: Generate docs (if API key present)
        AI-->>Action: Generated markdown
        Action->>API: Create companion PR with docs
        API-->>Action: PR info
    end
    Action->>API: Post PR comment (optional)
    Action->>GH: Write job summary & set outputs
    Action->>FS: Cleanup temp dir
Loading
sequenceDiagram
    participant GH as GitHub Actions
    participant Action as DocSync Action
    participant API as GitHub API
    participant Parser as File Parser
    participant FS as File System

    GH->>Action: Trigger on push to default branch
    Action->>API: Get repository default branch
    API-->>Action: Repo metadata
    Action->>FS: Scan & parse trackable files
    FS-->>Action: Parsed structures
    Action->>FS: Load existing snapshot (if any)
    FS-->>Action: Snapshot data
    alt Snapshot exists
        Action->>Action: analyzeDrift(snapshot, current)
        Action->>GH: Write analysis summary
    end
    Action->>FS: Write new snapshot
    FS-->>Action: Snapshot saved
    Action->>GH: Set outputs (files-analyzed, drift-score, drift-detected)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • test: trigger webhook #1 — Overlapping PR processing and companion-PR creation logic; likely related to PR handling and GitHub client usage.

Poem

🐰 I hopped through diffs and chased each stray line,

I counted constructs and ranked them just fine.
When drift blooms high, I sketch docs anew,
Propose a companion PR, tidy and true.
Hooray — DocSync hums; I’ve synced yours and mine.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'test: trigger GitHub Actions' is vague and does not clearly describe the main changes. The PR actually adds DocSync GitHub Action implementation with workflows, action manifest, and handlers, but the title only mentions 'triggering' actions without conveying the actual content being added. Revise the title to clearly describe the main changes, such as 'feat: add DocSync GitHub Action with PR and push workflows' or 'feat: implement DocSync action for documentation drift detection'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/actions-trigger

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 20 minutes and 4 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/docsync.yml:
- Around line 79-83: Replace the local action reference "uses: ./" with the
published action identifier so consumers don't resolve to their repo; update the
workflow step that currently has uses: ./ to use the released action tag (for
example, ishwar-prog/docsync@v1) so the workflow references the published action
version instead of a local path.

In `@src/action/index.js`:
- Around line 128-137: The validateInputs function currently calls
process.exit(1) after core.setFailed which bypasses the outer try/catch; remove
those process.exit calls and instead throw an Error (or rethrow) with the same
message so the error propagates to the top-level catch handler. Specifically, in
validateInputs replace the two process.exit(1) usages (the githubToken check and
the driftThreshold check) with thrown Error objects carrying the failure
message, keeping the core.setFailed call if you want the immediate log but
ensuring the thrown Error lets the surrounding async error handler run.

In `@src/action/pr-handler.js`:
- Around line 179-190: The current condition conflates true "no drift" with
"drift below threshold" by using if (!driftReport.hasDrift ||
driftReport.driftScore < inputs.driftThreshold); change the logic in the PR
handler so you first check driftReport.hasDrift (true/false) and only treat the
"no drift" path as when hasDrift is false; add a separate branch for hasDrift
=== true && driftReport.driftScore < inputs.driftThreshold that records/labels
"drift_below_threshold" (or similar) and does not call postNoDriftComment, and
ensure reporter.writeSummary receives distinct status values (e.g., 'in_sync' vs
'drift_below_threshold'); update references to postNoDriftComment and
reporter.writeSummary accordingly so messaging and labels reflect the actual
state.
- Around line 81-86: The handler exits early in multiple places without
guaranteeing the action outputs, so initialize the full output contract near the
start of the PR handler (e.g., after you read pullNumber/pr) by calling
core.setOutput('drift-detected','false') and core.setOutput('drift-score','0')
as defaults, then update/override those outputs later where real results are
computed; also audit every early-return branch (the draft check that inspects
pr.draft and other early returns that reference pullNumber/pr) and ensure each
branch either uses the initialized defaults or explicitly sets both
'drift-detected' and 'drift-score' before returning.

In `@src/action/push-handler.js`:
- Around line 60-63: In the early-return branch that checks
scanResult.totalFound === 0 in src/action/push-handler.js, set the Action
outputs (using core.setOutput) to sensible defaults before returning so
downstream steps don't receive blank values; specifically, inside that if block
assign the outputs your workflow expects (e.g., an empty list/empty string for
file/artifact outputs, zero for counts, and a status like "no_changes") and then
return. Ensure you update the same if block that contains the
scanResult.totalFound === 0 check so all expected outputs are always emitted.

In `@src/action/reporter.js`:
- Around line 36-40: The summary for the in_sync branch uses pullNumber directly
and can render "PR `#null`" on non-PR events; update the in_sync handling (the
block using status === 'in_sync' and summary.addRaw) to guard against a
null/undefined pullNumber by formatting the string conditionally (e.g., use
`pullNumber ? \`PR #${pullNumber}\` : 'push event'` or similar) before passing
it to summary.addRaw so the message never contains "PR `#null`".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4cab1c70-f036-4b90-82a1-774c19c00c88

📥 Commits

Reviewing files that changed from the base of the PR and between f5aadc9 and c182283.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .github/workflows/ci.yml
  • .github/workflows/docsync.yml
  • action.yml
  • package.json
  • src/action/index.js
  • src/action/pr-handler.js
  • src/action/push-handler.js
  • src/action/reporter.js
  • src/utils/logger.js

Comment thread .github/workflows/docsync.yml Outdated
Comment thread src/action/index.js
Comment thread src/action/pr-handler.js
Comment thread src/action/pr-handler.js Outdated
Comment thread src/action/push-handler.js
Comment thread src/action/reporter.js Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (1)
src/action/reporter.js (1)

27-31: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle drift_below_threshold explicitly in the summary.

src/action/pr-handler.js now passes a dedicated drift_below_threshold status, but this method still routes every non-in_sync case through the full “Documentation Drift Detected” path. That makes the summary read like an actionable failure instead of an intentional below-threshold no-op.

Also applies to: 36-46

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/action/reporter.js` around lines 27 - 31, The summary generator in
src/action/reporter.js currently treats every non-'in_sync' status as a full
"Documentation Drift Detected" case; add an explicit branch for the new
'drift_below_threshold' status in the function that reads params.status (the
method that builds the human-readable summary using params.driftReport,
params.generationSummary, params.pullNumber, and params.companionPR) so that
when status === 'drift_below_threshold' it returns a short, non-actionable
summary (e.g., "Drift detected but below threshold — no action required") and
avoids the full failure/error path used for 'drift_detected'; also update the
analogous logic block referenced around lines 36-46 to handle
'drift_below_threshold' similarly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/docsync.yml:
- Around line 66-74: The workflow contains a CI step named "Install
dependencies" that runs "npm ci", which should be removed because the template
action doesn't need to install consumer repo dependencies and this breaks
pnpm/yarn or lockfile-less repos; delete or disable the entire step block that
runs npm ci (the step with name "Install dependencies" and run: npm ci) or
replace it with a no-op/commented placeholder, ensuring no other steps reference
it.
- Around line 21-22: The workflow currently triggers on pull_request_target
types [opened, synchronize, reopened] which misses the draft -> ready_for_review
transition; update the pull_request_target types array in
.github/workflows/docsync.yml to include "ready_for_review" so that the handler
in src/action/pr-handler.js (which skips draft PRs) will run when a draft is
marked ready and the PR will be analyzed.
- Line 51: Replace floating action refs with immutable commit SHAs: locate the
uses entries for actions/checkout@v4, actions/setup-node@v4, and
ishwar-prog/docsync@v1 in the workflow and replace each tag (e.g., `@v4`, `@v1`)
with the corresponding full commit SHA (format @<40-char-sha>) from the official
repository commit for that release; ensure you fetch and paste the exact commit
SHA for each action, update the three refs (actions/checkout,
actions/setup-node, ishwar-prog/docsync), and scan the workflow for any other
floating refs to pin similarly.

In `@src/action/index.js`:
- Around line 110-119: readInputs currently exposes configPath but nothing
consumes it, so workflows using with: config-path get ignored; update the
pipeline to pass that configPath into the config loader and handlers: change
loadConfig(cwd) in push-handler.js (and any PR handler entry points) to accept
the configPath from readInputs (e.g., call loadConfig(cwd, inputs.configPath) or
similar), and modify src/utils/config.js's loader to accept and resolve the
provided configPath instead of always resolving 'docsync.yaml'; ensure
readInputs' configPath value is propagated from the action entry point into
whatever function calls loadConfig.
- Around line 29-34: The ESLint "no-undef" failures come from CommonJS files
using Node globals (require, process); fix by enabling the Node environment:
either add a file-level pragma ("/* eslint-env node */" and optionally "/*
globals require, process */") at the top of each CommonJS entry (e.g., the file
that imports core and github and references process.env and RUNNER_DEBUG, and
similarly in pr-handler.js and push-handler.js), or update the central
eslint.config.cjs to include env: { node: true } so require(), process, and
other Node globals are recognized; pick one approach and apply consistently
across files that export/require CommonJS modules (references: the require()
calls and process.env/RUNNER_DEBUG usages and the handlePullRequest/handlePush
imports).

In `@src/action/pr-handler.js`:
- Around line 3-16: This file has unused bindings causing ESLint failures:
remove the unused requires and parameters or make them used; specifically delete
the unused imports github and readSnapshot (or use them where needed), and if
you don't intend to call parseFiles here either remove its import or integrate
parseFiles() into the flow; change any catch((_)=>...) to catch((err)=>...) or
omit the unused `_` variable, and remove the unused driftReport parameter from
the postNoDriftComment function signature (or use it inside the function).
Update the top-level requires and the postNoDriftComment declaration accordingly
so no unused symbols remain.

---

Duplicate comments:
In `@src/action/reporter.js`:
- Around line 27-31: The summary generator in src/action/reporter.js currently
treats every non-'in_sync' status as a full "Documentation Drift Detected" case;
add an explicit branch for the new 'drift_below_threshold' status in the
function that reads params.status (the method that builds the human-readable
summary using params.driftReport, params.generationSummary, params.pullNumber,
and params.companionPR) so that when status === 'drift_below_threshold' it
returns a short, non-actionable summary (e.g., "Drift detected but below
threshold — no action required") and avoids the full failure/error path used for
'drift_detected'; also update the analogous logic block referenced around lines
36-46 to handle 'drift_below_threshold' similarly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b85d906-3cfa-4a78-9a0a-c41520d70b10

📥 Commits

Reviewing files that changed from the base of the PR and between c182283 and 2d79c21.

📒 Files selected for processing (7)
  • .github/workflows/ci.yml
  • .github/workflows/docsync.yml
  • eslint.config.cjs
  • src/action/index.js
  • src/action/pr-handler.js
  • src/action/push-handler.js
  • src/action/reporter.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/ci.yml

Comment thread .github/workflows/docsync.yml Outdated
Comment thread .github/workflows/docsync.yml Outdated
Comment thread .github/workflows/docsync.yml Outdated
Comment thread src/action/index.js
Comment thread src/action/index.js
Comment thread src/action/pr-handler.js
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/action/pr-handler.js`:
- Around line 414-474: The current flow always creates a timestamped
companionBranch and a new PR (createRef + pulls.create), causing duplicate
companion PRs; make companion PR creation idempotent by using a deterministic
branch name (e.g., `docsync/pr-${pullNumber}` instead of including Date.now()),
then before createRef/check createOrUpdateFileContents call try to fetch the ref
with octokit.rest.git.getRef for that branch and update it (update the ref) if
it exists or create it if not; next, search for an existing companion PR for
that head and source PR (use octokit.rest.pulls.list or search for open PRs with
head `${owner}:${companionBranch}`) and if found call octokit.rest.pulls.update
to update title/body (and ensure the branch is pushed), otherwise call
octokit.rest.pulls.create as currently done; reference companionBranch,
octokit.rest.git.createRef/getRef, octokit.rest.git.updateRef,
octokit.rest.repos.createOrUpdateFileContents, and
octokit.rest.pulls.create/pulls.update to implement this behavior.
- Around line 58-60: handlePullRequest is not loading the DocSync config
(inputs.configPath) so it uses extension-only filtering and the hardcoded
companion-doc path, ignoring track/ignore/output.dir/output.format; load the
same DocSync config used by the push path at the start of async function
handlePullRequest (using the project's existing config loader) and merge/apply
its track, ignore and output settings when computing companion doc paths and
filters instead of using hardcoded defaults; make the identical change in the
other PR-related blocks that mirror this logic so they all derive behavior from
the loaded config rather than hardcoded values.

In `@src/action/push-handler.js`:
- Around line 41-45: The call to octokit.rest.repos.get(...) that sets
defaultBranch is currently outside the existing try/catch, so network or
permission failures escape core.setFailed; move the repo lookup (the
octokit.rest.repos.get call and assignment to defaultBranch) into the same try
block that wraps the rest of the handler logic (and likewise move the other
external repo/default-branch lookup at the later site referenced) so any thrown
errors are caught and handled by the existing catch which calls core.setFailed;
ensure you keep the same variable name defaultBranch and do not create duplicate
declarations when relocating these calls.
- Line 3: Remove the unused "path" import to satisfy the linter: delete the
`const path = require('path');` statement in src/action/push-handler.js (the
unused symbol is `path`) so no-unused-vars CI error remains; ensure no other
code depends on `path` before removing and run tests/linter after change.

In `@src/utils/config.js`:
- Around line 56-62: The loadConfig function updates the missing-file warning to
use the configurable configFilename, but later log messages still hardcode
"docsync.yaml"; update all diagnostic messages in loadConfig (including success
and parse-error logs) to reference the configFilename or configPath variable
instead of the literal 'docsync.yaml' so messages reflect custom filenames (look
for usages in loadConfig of logger.warn/logger.info/logger.error and the
variables configFilename and configPath).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba32cec0-b89f-4e5f-bba2-ed8c37ca8c1a

📥 Commits

Reviewing files that changed from the base of the PR and between 2d79c21 and 92089f8.

📒 Files selected for processing (5)
  • .github/workflows/docsync.yml
  • eslint.config.cjs
  • src/action/pr-handler.js
  • src/action/push-handler.js
  • src/utils/config.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • eslint.config.cjs

Comment thread src/action/pr-handler.js
Comment on lines +58 to +60
async function handlePullRequest({ octokit, context, inputs }) {
const { repo } = context;
const pr = context.payload.pull_request;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Load DocSync config for PR runs too.

inputs.configPath is available here, but this handler never loads config. The extension-only filter and hardcoded companion-doc path ignore track, ignore, output.dir, and output.format, so PR drift can disagree with the snapshot built by src/action/push-handler.js and generate docs into the wrong location.

Also applies to: 107-111, 423-430

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/action/pr-handler.js` around lines 58 - 60, handlePullRequest is not
loading the DocSync config (inputs.configPath) so it uses extension-only
filtering and the hardcoded companion-doc path, ignoring
track/ignore/output.dir/output.format; load the same DocSync config used by the
push path at the start of async function handlePullRequest (using the project's
existing config loader) and merge/apply its track, ignore and output settings
when computing companion doc paths and filters instead of using hardcoded
defaults; make the identical change in the other PR-related blocks that mirror
this logic so they all derive behavior from the loaded config rather than
hardcoded values.

Comment thread src/action/pr-handler.js
Comment on lines +414 to +474
// Create companion branch
const companionBranch = `docsync/pr-${pullNumber}-${Date.now()}`;
await octokit.rest.git.createRef({
owner, repo,
ref: `refs/heads/${companionBranch}`,
sha: baseSha,
});
core.info(`Created branch: ${companionBranch}`);

// Commit documentation file
await octokit.rest.repos.createOrUpdateFileContents({
owner, repo,
path: 'docs/api-reference.md',
message: `docs: auto-generate documentation for PR #${pullNumber} [DocSync]`,
content: Buffer.from(docContent, 'utf8').toString('base64'),
branch: companionBranch,
});
core.info('Committed documentation file');

// Build PR body
const aiInfo = generationSummary
? `\n| AI Model | ${generationSummary.results[0]?.model || 'Llama 3.3 70B'} |`
: '';

const prBody = `## 📄 DocSync — Automated Documentation Update

This PR was automatically created by **DocSync** because PR #${pullNumber} introduced code changes that caused documentation drift.

### Drift Summary

| Metric | Value |
|--------|-------|
| Drift Score | **${driftReport.driftScore}/100** |
| Files Affected | ${driftReport.summary.filesAffected} |
| Total Changes | ${driftReport.summary.totalChanges} |${aiInfo}

### Changes Detected

${Object.entries(driftReport.summary.byType)
.map(([type, count]) => `- **${type}**: ${count} occurrence(s)`)
.join('\n')}

### Review Instructions

1. Open \`docs/api-reference.md\` to see the generated documentation
2. Review for accuracy — AI documentation is thorough but not omniscient
3. Make any necessary corrections
4. Merge this PR alongside or after PR #${pullNumber}

---
*🤖 Generated by [DocSync](https://github.com/ishwar-prog/docsync) — Docs that stay true to your code*`;

// Open the PR
const { data: companionPR } = await octokit.rest.pulls.create({
owner, repo,
title: `📄 DocSync: Update docs for PR #${pullNumber} — "${prTitle}"`,
body: prBody,
head: companionBranch,
base: baseBranch,
draft: false,
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Make companion PR creation idempotent.

This always creates a timestamped branch and then opens a new PR. Because .github/workflows/docsync.yml runs on synchronize with open-companion-pr: 'true', pushing multiple updates to the same source PR will accumulate multiple open DocSync PRs instead of refreshing one companion branch/PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/action/pr-handler.js` around lines 414 - 474, The current flow always
creates a timestamped companionBranch and a new PR (createRef + pulls.create),
causing duplicate companion PRs; make companion PR creation idempotent by using
a deterministic branch name (e.g., `docsync/pr-${pullNumber}` instead of
including Date.now()), then before createRef/check createOrUpdateFileContents
call try to fetch the ref with octokit.rest.git.getRef for that branch and
update it (update the ref) if it exists or create it if not; next, search for an
existing companion PR for that head and source PR (use octokit.rest.pulls.list
or search for open PRs with head `${owner}:${companionBranch}`) and if found
call octokit.rest.pulls.update to update title/body (and ensure the branch is
pushed), otherwise call octokit.rest.pulls.create as currently done; reference
companionBranch, octokit.rest.git.createRef/getRef, octokit.rest.git.updateRef,
octokit.rest.repos.createOrUpdateFileContents, and
octokit.rest.pulls.create/pulls.update to implement this behavior.

Comment thread src/action/push-handler.js Outdated
Comment on lines +41 to +45
const { data: repoData } = await octokit.rest.repos.get({
owner: repo.owner,
repo: repo.repo,
});
const defaultBranch = repoData.default_branch;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Move the default-branch lookup inside the existing try.

octokit.rest.repos.get(...) is the first external call in this handler, but it sits outside the catch that calls core.setFailed(...). A permission or network failure here escapes as an unhandled action error.

🔧 Suggested fix
-  const pushedBranch = context.ref.replace('refs/heads/', '');
-  const { data: repoData } = await octokit.rest.repos.get({
-    owner: repo.owner,
-    repo: repo.repo,
-  });
-  const defaultBranch = repoData.default_branch;
-
-  if (pushedBranch !== defaultBranch) {
-    core.info(`Push to ${pushedBranch} (not default branch ${defaultBranch}) — skipping snapshot update`);
-    return;
-  }
-
-  core.info(`Push to default branch ${defaultBranch} — updating snapshot`);
-
-  const cwd = process.cwd();
-
   try {
+    const pushedBranch = context.ref.replace('refs/heads/', '');
+    const { data: repoData } = await octokit.rest.repos.get({
+      owner: repo.owner,
+      repo: repo.repo,
+    });
+    const defaultBranch = repoData.default_branch;
+
+    if (pushedBranch !== defaultBranch) {
+      core.info(`Push to ${pushedBranch} (not default branch ${defaultBranch}) — skipping snapshot update`);
+      return;
+    }
+
+    core.info(`Push to default branch ${defaultBranch} — updating snapshot`);
+
+    const cwd = process.cwd();

Also applies to: 56-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/action/push-handler.js` around lines 41 - 45, The call to
octokit.rest.repos.get(...) that sets defaultBranch is currently outside the
existing try/catch, so network or permission failures escape core.setFailed;
move the repo lookup (the octokit.rest.repos.get call and assignment to
defaultBranch) into the same try block that wraps the rest of the handler logic
(and likewise move the other external repo/default-branch lookup at the later
site referenced) so any thrown errors are caught and handled by the existing
catch which calls core.setFailed; ensure you keep the same variable name
defaultBranch and do not create duplicate declarations when relocating these
calls.

Comment on lines +87 to +89
// Update the snapshot to reflect the current state
writeSnapshot(cwd, parsedFiles, { repoRoot: cwd });
core.info(`Snapshot updated: ${parsedFiles.length} file(s), ${parsedFiles.reduce((s, f) => s + f.constructCount, 0)} construct(s)`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== writeSnapshot implementation ==="
sed -n '1,260p' src/core/snapshot.js | nl -ba | sed -n '/writeSnapshot/,/module.exports/p'

echo
echo "=== push handler snapshot write ==="
sed -n '1,140p' src/action/push-handler.js | nl -ba | sed -n '80,100p'

echo
echo "=== workflow steps that could persist the updated snapshot ==="
rg -nC2 'git (add|commit|push)|createOrUpdateFileContents|peter-evans/create-pull-request' .github/workflows src/action

Repository: ishwar-prog/docsync

Length of output: 161


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking writeSnapshot implementation ==="
head -300 src/core/snapshot.js | grep -A 50 "function writeSnapshot\|const writeSnapshot\|writeSnapshot ="

echo
echo "=== Checking push handler lines 80-100 ==="
sed -n '80,100p' src/action/push-handler.js

echo
echo "=== Full push handler to understand context ==="
wc -l src/action/push-handler.js

echo
echo "=== Checking for git operations in workflow ==="
rg "git commit|git push|createOrUpdateFileContents|create-pull-request" .github/workflows/

echo
echo "=== Checking full docsync.yml workflow ==="
cat .github/workflows/docsync.yml

Repository: ishwar-prog/docsync

Length of output: 2971


🏁 Script executed:

cat .github/workflows/docsync.yml

Repository: ishwar-prog/docsync

Length of output: 3625


🏁 Script executed:

grep -r "git commit\|git push\|createOrUpdateFileContents\|gitAction\|updateFileContents" src/action/ src/core/

Repository: ishwar-prog/docsync

Length of output: 146


Commit the updated snapshot to the repository so baseline changes persist.

writeSnapshot() writes the snapshot only to the ephemeral runner filesystem. The push handler never commits or pushes this change, and the workflow has no follow-up persistence step. The updated snapshot disappears when the job ends, so the baseline never advances on push.

Comment thread src/utils/config.js
Comment on lines +56 to +62
function loadConfig(cwd = process.cwd(), configFilename = 'docsync.yaml') {
const configPath = path.resolve(cwd, configFilename);

// If no config file exists, that's fine — use all defaults.
// This is important: the tool should work without any configuration.
if (!fs.pathExistsSync(configPath)) {
logger.warn('No docsync.yaml found. Using default configuration.');
logger.warn(`No ${configFilename} found. Using default configuration.`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use the configurable filename in the remaining loadConfig() diagnostics.

This change updates the missing-file warning, but the success and parse-error messages later in the same function still hardcode docsync.yaml. Custom config paths will be misleading to debug.

🔧 Suggested fix
-    logger.info(`Config loaded from ${chalk.cyan('docsync.yaml')}`);
+    logger.info(`Config loaded from ${chalk.cyan(configFilename)}`);
...
-    logger.error(`Failed to parse docsync.yaml: ${error.message}`);
+    logger.error(`Failed to parse ${configFilename}: ${error.message}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/config.js` around lines 56 - 62, The loadConfig function updates
the missing-file warning to use the configurable configFilename, but later log
messages still hardcode "docsync.yaml"; update all diagnostic messages in
loadConfig (including success and parse-error logs) to reference the
configFilename or configPath variable instead of the literal 'docsync.yaml' so
messages reflect custom filenames (look for usages in loadConfig of
logger.warn/logger.info/logger.error and the variables configFilename and
configPath).

@ishwar-prog ishwar-prog merged commit 9672553 into main May 1, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant