# @file update-docs.yml
# @author @nichxbt
# @copyright (c) 2026 nich
# @repository universal-crypto-mcp
name: Update Docs
on:
push:
branches: [main]
paths-ignore:
- 'docs/**'
- '**/*.test.ts'
- '**/*.test.js'
- '**/__tests__/**'
- '**/test/**'
- '**/tests/**'
- '**/typescript/site/**'
- 'typescript/packages/legacy/**'
- 'go/legacy/**'
- 'python/legacy/**'
jobs:
update-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
env:
MINTLIFY_API_KEY: ${{ secrets.MINTLIFY_API_KEY }}
PROJECT_ID: ${{ secrets.MINTLIFY_PROJECT_ID }}
with:
script: |
const { owner, repo } = context.repo;
const projectId = process.env.PROJECT_ID;
const apiKey = process.env.MINTLIFY_API_KEY;
if (!projectId || !apiKey) {
core.setFailed('Missing MINTLIFY_PROJECT_ID or MINTLIFY_API_KEY secrets');
return;
}
// Get SHAs from push payload
const beforeSha = context.payload.before;
const afterSha = context.payload.after;
// Skip initial commits (no previous SHA to compare against)
if (/^0+$/.test(beforeSha)) {
core.notice('Initial commit detected. Skipping documentation update.');
return;
}
// Get changed files using GitHub Compare API (reliable for all merge types)
let uniqueFiles = [];
try {
const compareResponse = await github.rest.repos.compareCommits({
owner,
repo,
base: beforeSha,
head: afterSha
});
// Extract filenames, excluding test files and legacy packages
const excludePattern = /\.(test|spec)\.(ts|js|tsx|jsx)$|__tests__|\/test\/|\/tests\/|typescript\/packages\/legacy\/|go\/legacy\/|python\/legacy\//;
uniqueFiles = (compareResponse.data.files || [])
.map(f => f.filename)
.filter(f => !excludePattern.test(f));
} catch (error) {
core.setFailed('Failed to compare commits: ' + error.message);
return;
}
// Log changed files for debugging
console.log('Changed files (' + uniqueFiles.length + '):', uniqueFiles.slice(0, 10));
if (uniqueFiles.length > 10) {
console.log('... and ' + (uniqueFiles.length - 10) + ' more');
}
// Skip if no non-test files changed
if (uniqueFiles.length === 0) {
core.notice('No documentation-relevant files changed. Skipping agent trigger.');
return;
}
// Get commit message from head commit
const headCommit = context.payload.head_commit;
const commitMessage = headCommit
? '- ' + headCommit.message.split('\n')[0]
: '- No commit message available';
// Compare URL for reference
const compareUrl = context.payload.compare || '';
// Build the system prompt
const systemPrompt = [
'You are a documentation updater that ONLY updates docs directly related to specific code changes.',
'',
'CRITICAL RULES:',
'- ONLY update documentation that is directly affected by the code changes provided',
'- DO NOT perform general documentation audits or sync operations',
'- DO NOT add documentation for unrelated features, ecosystem partners, or missing content',
'- If the code changes do not require documentation updates, report "No documentation updates needed" and exit without creating a PR',
'- Focus on the specific files and commits mentioned, not the entire repository state',
'- Read the AGENTS.md file in the docs directory for additional guidance'
].join('\n');
// Build the user prompt
const userPrompt = [
'Review these SPECIFIC code changes and update documentation ONLY if directly related:',
'',
'**Repository:** ' + owner + '/' + repo,
'**Compare URL:** ' + compareUrl,
'',
'**Changed Files (' + uniqueFiles.length + '):**',
uniqueFiles.join('\n'),
'',
'**Commit Message:**',
commitMessage,
'',
'IMPORTANT: Only update documentation that is directly impacted by these specific file changes. Do not add documentation for unrelated features or perform general audits. If these changes do not affect documentation, do NOT create a PR.'
].join('\n');
const url = 'https://api.mintlify.com/v1/agent/' + projectId + '/job';
const payload = {
branch: 'mintlify/docs-update-' + Date.now(),
messages: [
{
role: 'system',
content: systemPrompt
},
{
role: 'user',
content: userPrompt
}
],
asDraft: false
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
const errorText = await response.text();
throw new Error('API request failed with status ' + response.status + ': ' + errorText);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim()) {
console.log(line);
}
}
}
if (buffer.trim()) {
console.log(buffer);
}
core.notice('Documentation update job triggered for ' + owner + '/' + repo);
} catch (error) {
core.setFailed('Failed to create documentation update job: ' + error.message);
}
# ucm:n1ch98c1f9a1