ð 仿§æžãã³ãŒããšäžç·ã«æŽæ°ãããïŒGitHub Wikiãã䜿ããããã¥ã¡ã³ããã«ããèªååæã®ä»çµã¿ãæ§ç¯ããŠã¿ã
ã¯ããã«
éçºã«ç±äžãããšã€ãã€ãããã¥ã¡ã³ãæŽæ°ãåŸåãã«ããã¡ãªçããããå æ°ã§ãã(èªæ)ïŒ
ãã³ãŒãã¯ææ°ã®ä»æ§ã«ãªã£ãŠããã®ã«ãããã¥ã¡ã³ãã¯3ã¶æåã®ãŸãŸ...ã
ãWikiã®ç·šéç»é¢ã ãšã¬ãã¥ãŒã§ããªãããããã€ã®éã«ã仿§ãå€ãã£ãŠããŠé©ã...ã
ãããããWiki䜿ã£ãŠãªãããExceléãã®ã¯ããã©ãããNotionã¯PMãè§Šã£ãŠãã...ã
ãã㪠ãããã¥ã¡ã³ãå šç¶æŽæ°ãããªãåé¡ã ã«çµæ¢ç¬Šãæã€ã¹ããä»åã¯
- Everything as a Code ãIaCã«ããã仿§æžãã³ãŒãã«ãã¡ããã
- Single Source of Truthãæ å ±ã¯æ£ä¹±ãããã«åäžéçŽïœ¯ïœ¯ïœ¯ã
ã®ç²Ÿç¥ã«åºã¥ããããã¥ã¡ã³ã管çã·ã¹ãã ãå°å ¥ããŠã¿ãŸããã
ã³ãŒããšåããªããžããªã§ä»æ§æžã管çããGitHub Actionsã§åæã«WikiãžåæããŠãããè¯ãããªä»çµã¿ã§ãã
仿§æžãMarkdown圢åŒã§Git管çããããããAIãå
容ãè§£æãããããèŠçŽã質åå¿çãªã©ã®æŽ»çšãæåŸ
ã§ããŸãã
ã©ããªãã®ãäœã£ãã®ã

ã©ããªä»çµã¿ïŒ
ä»çµã¿ã¯ããã£ãŠã·ã³ãã«ã§ãã
ãªããžããªã® docs/wiki/ ãã£ã¬ã¯ããªé
äžããæ£ããšãªãããŒã¿ãœãŒã¹ã§ããããã«å€æŽãããŒãžããããšãGitHub ActionsãåããGitHub Wikiå°çšã®ãªããžããªãžå
容ã匷å¶çã«åæïŒpushïŒããŸãã
ãããã¥ã¡ã³ããæŽæ°ããããšããã¿ã¹ã¯ããããã¡ã€ã«ãä¿®æ£ããŠPRãåºãããšããæ®æ®µã®éçºãããŒã«å®å
šã«çµ±åãããã®ãããœã§ãã
ã³ãŒãã®ä¿®æ£ã€ãã§ã«ããŸãã仿§æžãã¡ãã¡ãã£ãšå€ããšããããã§ããã®ãäœããè¯ãâšïž
ãã ãããã€ã³ããšãããããã誀ç®
å®éã«ãã®éçšãåããŠã¿ãŠãæ³å以äžã«è¯ãã£ããã€ã³ããããã€ããããŸãã
1. ã³ãŒããšããã¥ã¡ã³ããã»ããã§ã¬ãã¥ãŒã§ããïŒããããã«ãïŒ
æ©èœä¿®æ£ã®PRã®äžã«ã仿§æžã®å€æŽãå«ãŸããŠããã°ããå®è£ ãšä»æ§ã®ãºã¬ãããã®å Žã§ææã§ããŸãã
GitHubã®Diffç»é¢ã§ã³ãŒããšä»æ§æžãè¡ãæ¥ããªããã¬ãã¥ãŒã§ããã®ã¯ãäœéšãšããŠããªãè¯ãã§ãããããå®è£ å€ãã£ããã©ããã¥ã¡ã³ãçŽã£ãŠãªããªãïŒããæ¿æžããŸãã
2. WikiãèŠããããã¥ãŒã¢ãŒã«ãªã
ãªããžããªå
ã®Markdownãã¡ã€ã«ïŒdocs/wiki/*.mdïŒãçŽæ¥GitHubã®ãã¡ã€ã«ãã¥ãŒã¢ãŒã§æ¢ããŠèªãã®ã¯ããšã³ãžãã¢ä»¥å€ïŒPMããã¶ã€ããŒãªã©ïŒã«ã¯å°ãããŒãã«ãé«ãã§ãã
ãšã³ãžãã¢ãã¬ã³ããªã³ã°ãããŠããªãMarkdownãã¡ã€ã«ãèªãã®ã¯å«ã§ãããã
GitHub Wikiã«åæãããŠããã°ãã¬ã³ããªã³ã°ããã綺éºãªç¶æ ãã€ãããŸãã§ãµã€ãããŒãã€ããŠèª°ã§ãé²èЧã§ããŸãã
äžå ·åã®ä¿®æ£ãè¡ãéãªã©ã¯ãæ£ãšãã仿§æžãWikiã«ã¬ã³ããªã³ã°ãããç¶æ ã§ããã®ã§ãPRã«ãªã³ã¯ãå·®ã蟌ãã ãã§ããŸãã
3. ã[private]ãã¬ãã£ãã¯ã¹ãã§ããšã ãæžãã(ç¬)
ããšã ãšããã®ã¯åååè«ã§ãããèŠã¯ DBãžã®æ¥ç¶æ
å ±ãç°å¢å€æ°ã®å€ãªã©ã®æ©å¯æ
å ± ã¯ãã®ä»çµã¿ã§ç®¡çã§ããŸãã
ã[private]ã ãšãããã¬ãã£ãã¯ã¹ããã¡ã€ã«åã«ä»ããããŒãžã¯åæå¯Ÿè±¡å€ãšããŠä¿è·ãããããã«ããŸããã
ã仿§æžã¯å³æ Œã«Git管çãããããã©ãããŸã 仿§ãšããŠåºãŸã£ãŠããªãå人çãªã¡ã¢ãããããŒã å ã ãã®ç§å¯ã®å ±æäºé ïŒæ¥ç¶æ å ±etcïŒããŸã§PRããŒã¹ã§ç®¡çããã®ã¯é¿ããããšããã§ãã
- 仿§æž: Git管çïŒåæãããïŒ
- æ©å¯æ å ±: Wikiã§çŽæ¥ç·šéïŒåæãããªãã»æ¶ãããªãïŒ
- ã¡ã¢ã»ããšã : Wikiã§çŽæ¥ç·šéïŒåæãããªãã»æ¶ãããªãïŒ
ãã®ã峿 Œãããšãããããã®ãã€ããªãããªéçšãã§ããã®ãããã®ä»çµã¿ã®æ°ã«å ¥ã£ãŠãããšããã§ãã
å°å ¥æ¹æ³
Step 1: Github Wikiã®æå¹å & åæããŒãžäœæ
調ã¹ãã°ããããåºãŠããã¯ãã§ãã®ã§å²æããŸãã
â»Githubã®ç¡æãã©ã³ãå©çšãããŠããæ¹ã¯ãpublicãªããžããªã§ããWikiã¯äœãããšãã§ããŸãããïŒææãã©ã³ã§ããã°åé¡ãªãã¯ãã§ãïŒ


Step 2: åæçšã¹ã¯ãªããã®äœæ
ãããžã§ã¯ãã®ã«ãŒãã« scripts/sync-docs-to-wiki.js ãäœæãã以äžã®ã³ãŒãã貌ãä»ããŠãã ãããäŸåã©ã€ãã©ãªã¯ãããŸããïŒNode.jsã®æšæºã¢ãžã¥ãŒã«ã®ã¿äœ¿çšïŒã
ã¡ãªã¿ã«ç§ã¯Next.jsã®ãããžã§ã¯ãå
ã«é
眮ããŠå©çšããŠããŸãã
scripts/sync-docs-to-wiki.jsïŒã¯ãªãã¯ã§å±éïŒ
#!/usr/bin/env node
/**
* docs/ é
äžã®èšèšæžã GitHub Wiki ã«åæããã¹ã¯ãªãã
*
* ãã®ã¹ã¯ãªããã¯GitHub Actionsç°å¢ã§ã®ã¿å®è¡å¯èœã§ãã
* ããŒã«ã«ç°å¢ããã®å®è¡ã¯èš±å¯ãããŠããŸããã
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
// ç°å¢å€æ°ã®ååŸ
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const GITHUB_REPO = process.env.GITHUB_REPO || process.env.GITHUB_REPOSITORY;
const GITHUB_ACTIONS = process.env.GITHUB_ACTIONS === 'true';
// GitHub Actionsç°å¢ã§ã®ã¿å®è¡ãèš±å¯
if (!GITHUB_ACTIONS) {
console.error('â ãã®ã¹ã¯ãªããã¯GitHub Actionsç°å¢ã§ã®ã¿å®è¡ã§ããŸã');
console.error(' ããŒã«ã«ç°å¢ããã®å®è¡ã¯èš±å¯ãããŠããŸãã');
console.error(' Wikiåæã¯GitHub Actionsããèªåçã«å®è¡ãããŸã');
process.exit(1);
}
if (!GITHUB_TOKEN) {
console.error('â GITHUB_TOKEN ç°å¢å€æ°ãèšå®ãããŠããŸãã');
process.exit(1);
}
if (!GITHUB_REPO) {
console.error('â GITHUB_REPO ç°å¢å€æ°ãèšå®ãããŠããŸãã');
console.error(' äŸ: GITHUB_REPO=owner/repo');
process.exit(1);
}
const [owner, repo] = GITHUB_REPO.split('/');
if (!owner || !repo) {
console.error('â GITHUB_REPO ã®åœ¢åŒãæ£ãããããŸãã');
console.error(' äŸ: GITHUB_REPO=owner/repo');
process.exit(1);
}
// ããã¯å®éã®æ§æã«åãããŠå€æŽããŠãã ãã
const DOCS_DIR = path.join(process.cwd(), 'docs', 'wiki');
// Wiki ã«ã®ã¿æ®ãã¹ãããŒãžïŒåé€å¯Ÿè±¡å€ïŒ
// [private] ã§å§ãŸãããŒãžã¯èªåçã«ä¿è·ãããŸã
const PROTECTED_WIKI_PAGES = [];
/**
* docs/wiki/ é
äžã® Markdown ãã¡ã€ã«ãååž°çã«ååŸ
*/
function getMarkdownFiles(dir, basePath = '') {
const files = [];
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
const relativePath = path.join(basePath, entry.name);
if (entry.isDirectory()) {
// ãµããã£ã¬ã¯ããªãå«ãã
files.push(...getMarkdownFiles(fullPath, relativePath));
} else if (entry.isFile() && entry.name.endsWith('.md')) {
files.push({
filePath: fullPath,
relativePath: relativePath,
wikiTitle: getWikiTitle(relativePath),
});
}
}
return files;
}
/**
* ãã¡ã€ã«ãã¹ãã Wiki ããŒãžã¿ã€ãã«ãçæ
*/
function getWikiTitle(relativePath) {
// ãã¡ã€ã«åããæ¡åŒµåãé€å»
const nameWithoutExt = relativePath.replace(/\.md$/, '');
// ãã¹åºåãããã€ãã³ã«å€æïŒå¿
èŠã«å¿ããŠèª¿æŽïŒ
// äŸ: "01_èŠä»¶å®çŸ©æž" -> "01_èŠä»¶å®çŸ©æž"
// äŸ: "01_èŠä»¶å®çŸ©æž/顧客èŠä»¶" -> "01_èŠä»¶å®çŸ©æž-顧客èŠä»¶"
return nameWithoutExt.replace(/\//g, '-');
}
/**
* Wiki ããŒãžãäœæãŸãã¯æŽæ°ïŒGitãªããžããªçµç±ïŒ
*/
function createOrUpdateWikiPage(title, content, wikiDir) {
const fileName = `${title}.md`;
const filePath = path.join(wikiDir, fileName);
// ãã¡ã€ã«ãæ¢ã«ååšããã確èª
const exists = fs.existsSync(filePath);
// ãã¡ã€ã«ãæžã蟌ã¿
fs.writeFileSync(filePath, content, 'utf-8');
// Gitã«è¿œå
execSync(`cd "${wikiDir}" && git add "${fileName}"`, { stdio: 'pipe' });
if (exists) {
console.log(`â
æŽæ°: ${title}`);
} else {
console.log(`âš äœæ: ${title}`);
}
}
/**
* Wiki ãªããžããªãããã¹ãŠã®ããŒãžãååŸïŒGitæäœã®ã¿ïŒ
*/
function getAllWikiPages(wikiDir) {
const pages = [];
if (!fs.existsSync(wikiDir)) {
return [];
}
const files = fs.readdirSync(wikiDir);
for (const file of files) {
if (file.endsWith('.md')) {
const title = file.replace(/\.md$/, '');
// ã·ã¹ãã ããŒãžã¯é€å€
if (title !== '_Sidebar' && title !== 'Home') {
pages.push({
title: title,
fileName: file,
});
}
}
}
return pages;
}
/**
* ããŒãžã¿ã€ãã«ãä¿è·å¯Ÿè±¡ãã©ãããå€å®
*/
function isProtectedPage(title) {
// [private] ã§å§ãŸãããŒãžã¯ä¿è·å¯Ÿè±¡
if (title.startsWith('[private]')) {
return true;
}
// æç€ºçã«æå®ãããä¿è·å¯Ÿè±¡ããŒãž
return PROTECTED_WIKI_PAGES.some(protectedPage => {
// å®å
šäžèŽãŸãã¯ãã¹ã©ãã·ã¥/ãã€ãã³ã®éããèæ
®
return title === protectedPage ||
title === protectedPage.replace(/\//g, '-') ||
title === protectedPage.replace(/-/g, '/');
});
}
/**
* Wiki ããŒãžãåé€ïŒGitæäœã®ã¿ïŒ
*/
function deleteWikiPages(wikiDir, pagesToDelete) {
if (pagesToDelete.length === 0) {
return 0;
}
let deletedCount = 0;
for (const pageTitle of pagesToDelete) {
const fileName = `${pageTitle}.md`;
const filePath = path.join(wikiDir, fileName);
if (fs.existsSync(filePath)) {
execSync(`cd "${wikiDir}" && git rm "${fileName}"`, { stdio: 'pipe' });
console.log(`ðïž åé€: ${pageTitle}`);
deletedCount++;
}
}
return deletedCount;
}
/**
* ã¡ã€ã³åŠç
*/
function main() {
console.log(`ð ${GITHUB_REPO} ã® Wiki ã«åæãéå§ããŸã...\n`);
// docs/wiki/ ãã£ã¬ã¯ããªã®ååšç¢ºèª
if (!fs.existsSync(DOCS_DIR)) {
console.error(`â docs/wiki/ ãã£ã¬ã¯ããªãèŠã€ãããŸãã: ${DOCS_DIR}`);
process.exit(1);
}
// Markdown ãã¡ã€ã«ã®ååŸ
const files = getMarkdownFiles(DOCS_DIR);
console.log(`ð ${files.length} åã® Markdown ãã¡ã€ã«ãèŠã€ãããŸãã\n`);
// Wikiãªããžããªãã¯ããŒã³
const wikiDir = path.join(process.cwd(), '.wiki-temp');
// GitHub Actionsç°å¢ã§ã¯ãURLã«çŽæ¥ããŒã¯ã³ãåã蟌ãïŒãŠãŒã¶ãŒåã« x-access-token ãå©çšïŒ
const encodedToken = encodeURIComponent(GITHUB_TOKEN);
const wikiRepoUrl = `https://x-access-token:${encodedToken}@github.com/${owner}/${repo}.wiki.git`;
const gitUserName = process.env.GITHUB_ACTOR || 'github-actions[bot]';
const gitUserEmail = process.env.GIT_COMMIT_EMAIL || `${gitUserName}@users.noreply.github.com`;
try {
// GitHub Actionsç°å¢ã§ã®GitèªèšŒèšå®
// GIT_TERMINAL_PROMPTã0ã«èšå®ããŠãã¹ã¯ãŒãããã³ãããç¡å¹å
const gitEnv = {
...process.env,
GIT_TERMINAL_PROMPT: '0',
GIT_ASKPASS: 'echo',
};
if (!fs.existsSync(wikiDir)) {
console.log('ð¥ Wiki ãªããžããªãã¯ããŒã³äž...\n');
execSync(`git clone "${wikiRepoUrl}" "${wikiDir}"`, {
stdio: 'inherit',
env: gitEnv
});
} else {
execSync(`cd "${wikiDir}" && git pull origin master`, {
stdio: 'pipe',
env: gitEnv
});
}
// ãªã¢ãŒãURLãèªèšŒä»ãURLã«æŽæ°ïŒæ¢åã¯ããŒã³å¯ŸçïŒ
execSync(`cd "${wikiDir}" && git remote set-url origin "${wikiRepoUrl}"`, {
stdio: 'pipe',
env: gitEnv,
});
// GitãŠãŒã¶ãŒæ
å ±ãèšå®
execSync(`cd "${wikiDir}" && git config user.name "${gitUserName}"`, {
stdio: 'pipe',
env: gitEnv,
});
execSync(`cd "${wikiDir}" && git config user.email "${gitUserEmail}"`, {
stdio: 'pipe',
env: gitEnv,
});
// Wiki ãªããžããªããæ¢åã®ããŒãžãååŸ
const wikiPages = getAllWikiPages(wikiDir);
const docsWikiTitles = new Set(files.map(f => f.wikiTitle));
// ä¿è·å¯Ÿè±¡ããŒãžãååŸïŒãµã€ãããŒã«å«ããããïŒ
const protectedPages = wikiPages
.filter(page => {
const title = page.title;
return isProtectedPage(title);
})
.map(page => ({
title: page.title,
wikiTitle: page.title,
fileName: page.fileName,
}));
// ãã¹ãŠã®ãã¡ã€ã«ã远å
for (const file of files) {
const content = fs.readFileSync(file.filePath, 'utf-8');
createOrUpdateWikiPage(file.wikiTitle, content, wikiDir);
}
// ãµã€ãããŒãäœæ
const sidebarContent = `# ç®æ¬¡
${files
.filter(f => !f.relativePath?.includes('wiki-backup'))
.map(f => `- [[${f.wikiTitle}|${f.wikiTitle}]]`)
.join('\n')}
${protectedPages.length > 0 ? `## Wiki å°çšããŒãž\n\n${protectedPages.map(p => `- [[${p.wikiTitle}|${p.wikiTitle}]]`).join('\n')}\n` : ''}
`;
createOrUpdateWikiPage('_Sidebar', sidebarContent, wikiDir);
// åé€å¯Ÿè±¡ã®ããŒãžãåŠç
const pagesToDelete = wikiPages
.filter(page => {
const title = page.title;
// ä¿è·å¯Ÿè±¡ããŒãžã¯åé€ããªã
if (isProtectedPage(title)) {
return false;
}
// docs/wiki/ ã«ååšããªãããŒãžã®ã¿åé€å¯Ÿè±¡
return !docsWikiTitles.has(title);
})
.map(page => page.title);
// ä¿è·å¯Ÿè±¡ããŒãžã®ç¢ºèªãã°
const allProtectedPages = wikiPages.filter(page => isProtectedPage(page.title));
if (allProtectedPages.length > 0) {
console.log(`\nð ä¿è·ããã Wiki ããŒãžïŒåé€å¯Ÿè±¡å€ïŒ: ${allProtectedPages.length} å`);
allProtectedPages.forEach(page => console.log(` - ${page.title}`));
}
if (pagesToDelete.length > 0) {
console.log(`\nðïž åé€å¯Ÿè±¡ã® Wiki ããŒãž: ${pagesToDelete.length} å`);
pagesToDelete.forEach(title => console.log(` - ${title}`));
deleteWikiPages(wikiDir, pagesToDelete);
} else {
console.log('\nâ
åé€å¯Ÿè±¡ã®ããŒãžã¯ãããŸããã§ãã');
}
// 倿Žãããã確èªããŠã³ãããã»ããã·ã¥
try {
execSync(`cd "${wikiDir}" && git diff --cached --quiet`, { stdio: 'pipe' });
console.log('\nâ
倿Žã¯ãããŸããã§ãã');
} catch {
// 倿Žãããå Žåã¯ã³ãããã»ããã·ã¥
console.log('\nðŸ 倿Žãã³ãããäž...');
execSync(`cd "${wikiDir}" && git commit -m "Sync docs/wiki to GitHub Wiki"`, { stdio: 'inherit' });
console.log('ð€ 倿Žãããã·ã¥äž...');
execSync(`cd "${wikiDir}" && git push origin master`, {
stdio: 'inherit',
env: gitEnv
});
console.log('\nâ
Wikiãžã®åæãå®äºããŸããïŒ');
}
} finally {
// äžæãã£ã¬ã¯ããªãã¯ãªãŒã³ã¢ãã
if (fs.existsSync(wikiDir)) {
execSync(`rm -rf "${wikiDir}"`, { stdio: 'pipe' });
}
}
}
try {
main();
} catch (error) {
console.error('\nâ ãšã©ãŒãçºçããŸãã:', error);
process.exit(1);
}
Step 3: GitHub Actionsã®ã¯ãŒã¯ãããŒäœæ
.github/workflows/sync-wiki.yml ãäœæããŸãã
ããããŸãç¹å¥ãªäŸåé¢ä¿ã¯äžèŠã§ãæšæºç㪠Node.js ç°å¢ãããã°åäœããŸãã
name: Sync Docs to Wiki
on:
push:
branches:
- main
- develop
paths:
- 'docs/wiki/**/*.md'
workflow_dispatch: # æåå®è¡ãå¯èœ
jobs:
sync-wiki:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"
- name: Sync docs to Wiki
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPO: ${{ github.repository }}
run: node scripts/sync-docs-to-wiki.js
Step 4: ãµã³ãã«ãã¡ã€ã«ã远å ããŠå®è¡ããŠã¿ã
ãµã³ãã«ãšããŠãããªéå±€ã®ãã¡ã€ã«ã远å ããŠã¿ãŸãã
docs/wiki/
âââ Home.md
âââ 01_èŠä»¶å®çŸ©æž/
â âââ éçºèŠä»¶.md
â âââ 顧客èŠä»¶.md
âââ 02_æš©éèšèšæž/
âââ äžè¬ãŠãŒã¶ãŒ.md
âââ 管çè
ãŠãŒã¶ãŒ.md
åèãŸã§ã«ãç§ã¯Home.mdã«ãã®ãããªèšèŒãå ¥ããŠçè§£ãä¿ããŠããŸãã
docs/wiki/Home.mdïŒã¯ãªãã¯ã§å±éïŒ
# Wiki ã®æŠèŠ
ãã® Wiki ã¯ãœãŒã¹ã³ãŒãåŽãªããžããªå
ã® `docs/wiki` ãã£ã¬ã¯ããªã«ãã Markdown ãã¡ã€ã«ãšåæãããŠããŸãã
- åæå¯Ÿè±¡: `docs/wiki` é
äžã® `.md` ãã¡ã€ã«
- é€å€å¯Ÿè±¡: ãã¡ã€ã«åïŒããŒãžã¿ã€ãã«ïŒã `[private]` ã§å§ãŸãããŒãžã¯åæãããŸãã
èšèšæžãåçš®ããã¥ã¡ã³ãã®æŽæ°ã¯ `docs/wiki` é
äžã§è¡ãã`main` ãŸã㯠`develop` ãã©ã³ãã«å€æŽãããã·ã¥ããããšã§èªåçã« Wiki ãžåæ ãããŸãã
> [!WARNING]
> Wiki äžã§çŽæ¥ç·šéããå
å®¹ã¯æ¬¡ã®åæã§äžæžããããŸããå¿
ããªããžããªã® `docs/wiki` é
äžã§ç·šéããŠãã ããã
> [!IMPORTANT]
> ç§å¿æ
å ±ãªã© Wiki ã®ã¿ã§ä¿æãããå
容ãããå Žåã¯ãããŒãžã¿ã€ãã«ã `[private]` ã§å§ããŠã³ã³ãœãŒã«äžããç·šéããŠãã ããïŒåæå¯Ÿè±¡å€ã«ãªããŸãïŒã
å®è£ ã®è£åŽïŒéçºè åãïŒ
åæåŠçã®å¿èéšã¯ scripts/sync-docs-to-wiki.js ãšããNode.jsã¹ã¯ãªããã§ãã
ãã ãã¡ã€ã«ãã³ããŒããã ãã§ãªããéçºäœéšãæãªããªãããã®ãæ°ã®å©ããåŠçðããããã€ãå
¥ããŠããŸãã
ãã£ã¬ã¯ããªéå±€ããã©ããã«å€æ
ãªããžããªå ã§ã¯æŽçã®ããã«ãã£ã¬ã¯ããªãåãããã§ãããGitHub Wikiã¯ãã©ãããªæ§é ããæã¡ãŸãããããã§ããã¡ã€ã«ãã¹ã®ã¹ã©ãã·ã¥ããã€ãã³ã«çœ®æããŠãäžæãªã¿ã€ãã«ãçæããŠããŸãã
function getWikiTitle(relativePath) {
// äŸ: "akfm-knowledge/part_1.md" -> "akfm-knowledge-part_1"
const nameWithoutExt = relativePath.replace(/\.md$/, '');
return nameWithoutExt.replace(/\//g, '-');
}
ãµã€ãããŒã®èªåçæ
Wikiã®ãµã€ãããŒïŒ_SidebarïŒãæåã§æŽæ°ããã®ã¯é¢åãããŸãïŒçµ¶å¯ŸæŽæ°å¿ãããã€ïŒã
ã ããããããã¡ã€ã«äžèЧããåæã«äœã£ãŠãããããã«ããŸããã
// scripts/sync-docs-to-wiki.js ããæç²ïŒé°å²æ°ïŒ
const sidebarContent = `# ç®æ¬¡
${files
.map(f => `- [[${f.wikiTitle}|${f.wikiTitle}]]`)
.join('\n')}
${protectedPages.length > 0 ? `## Wiki å°çšããŒãž\n\n${protectedPages.map(p => `- [[${p.wikiTitle}|${p.wikiTitle}]]`).join('\n')}\n` : ''}
`;
ããã§ããã¡ã€ã«ã远å ããã ãã§Wikiã®ç®æ¬¡ãæŽæ°ãããŸããæé«ã
ã[private]ãããŒãžã®ä¿è·ããžãã¯
åè¿°ãããããšã ä¿è·æ©èœ(ç¬)ãã®å®è£
ã§ãã
åæã¹ã¯ãªããã¯åºæ¬çã«ããªããžããªã«ãªãWikiããŒãžã¯ãŽããšã¿ãªããŠåé€ããããšããæåãããŸããããã®ãã¬ãã£ãã¯ã¹ãããå Žåã ãã¯ç¹å¥æ±ãããŠåé€ãã¹ãããããŸãã
function isProtectedPage(title) {
// [private] ã§å§ãŸãããŒãžã¯ä¿è·å¯Ÿè±¡
if (title.startsWith('[private]')) {
return true;
}
return false;
}
// åé€åŠçã®äžã§...
const pagesToDelete = wikiPages.filter(page => {
// ä¿è·å¯Ÿè±¡ãªãåé€ãªã¹ãã«å
¥ããªãïŒ
if (isProtectedPage(page.title)) return false;
// ãªããžããªã«ååšããªããªãåé€
return !docsWikiTitles.has(page.title);
});
åèãŸã§ã«ïŒGithubïŒ
ãŸãšã
ããã¥ã¡ã³ã管çã¯ãç¶ç¶ã§ããããšããšãææ°çãç¹å®ã§ããããšããäžçªå€§äºã ãšæã£ãŠããŸãã
ãšãããããã®ä»çµã¿ãå°å
¥ããŠãããŒã å
ã§ããã¥ã¡ã³ã管çã«ãã©ã€ããŠããŸãã
Claude Codeã®Hooksã§ãã£ãŠè²°ãæ¹æ³ãããã®ããªãŒãªããŠæã£ãŠããããŠããŸãã
æ©å¯æ å ±ã®åãæ±ãã«ã¯ååãæ³šæãã ãããŸãã
ãã¬ããã°ã«ãŒã ã·ã¹ãã ãããããã¡ã³ãã«ã³ãããŒã§ã¯ãå€çš®å€æ§ãªããŒãºã«ãããã·ã¹ãã ã®äŒç»ã»ç«æ¡ããããã°ã©ã ã®éçºãå¿ èŠãªããŒããŠã§ã¢ã»ãœãããŠã§ã¢ã®éžå®ã»å°å ¥ãŸã§ãäžæ°é貫ããŠæäŸããŠããŸãã
Discussion