Skip to content

Commit 252867d

Browse files
committed
first commit
0 parents  commit 252867d

6 files changed

Lines changed: 219 additions & 0 deletions

File tree

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
name: Aggregate Docs
2+
3+
on:
4+
push:
5+
branches: [main]
6+
repository_dispatch:
7+
types: [docs-updated]
8+
schedule:
9+
- cron: '0 0 * * *'
10+
workflow_dispatch:
11+
12+
concurrency:
13+
group: aggregate-docs
14+
cancel-in-progress: true
15+
16+
permissions:
17+
contents: write
18+
19+
jobs:
20+
aggregate:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v4
24+
25+
- uses: actions/github-script@v8
26+
name: Aggregate docs from source repos
27+
env:
28+
PUSH_TOKEN: ${{ secrets.DOCS_PUSH_TOKEN }}
29+
with:
30+
script: |
31+
const fs = require('fs');
32+
const path = require('path');
33+
34+
// Read config files
35+
const repos = JSON.parse(fs.readFileSync('repos.json', 'utf8'));
36+
const docsConfig = JSON.parse(fs.readFileSync('docs.json', 'utf8'));
37+
38+
// Reset products array (start fresh each run)
39+
docsConfig.navigation.products = [];
40+
41+
// Create a temp working directory for the aggregated output
42+
const outDir = path.join(process.env.RUNNER_TEMP, 'aggregated');
43+
await io.mkdirP(outDir);
44+
45+
// Copy base assets and config
46+
await io.cp('assets', path.join(outDir, 'assets'), { recursive: true });
47+
48+
// Copy any top-level MDX pages from the docs repo itself
49+
for (const file of fs.readdirSync('.')) {
50+
if (file.endsWith('.mdx')) {
51+
await io.cp(file, path.join(outDir, file));
52+
}
53+
}
54+
55+
// Process each source repo
56+
for (const { owner, repo, docsPath = 'docs', ref = 'main' } of repos) {
57+
core.startGroup(`Processing ${owner}/${repo}`);
58+
59+
const cloneDir = path.join(process.env.RUNNER_TEMP, 'repos', repo);
60+
await io.rmRF(cloneDir);
61+
62+
// Clone the repo (shallow, specific branch)
63+
await exec.exec('git', [
64+
'clone', '--depth=1', '--branch', ref,
65+
`https://x-access-token:${process.env.PUSH_TOKEN}@github.com/${owner}/${repo}.git`,
66+
cloneDir
67+
]);
68+
69+
const sourceDir = path.join(cloneDir, docsPath);
70+
const sourceConfig = path.join(sourceDir, 'docs.json');
71+
72+
if (!fs.existsSync(sourceConfig)) {
73+
core.warning(`No docs.json found in ${owner}/${repo}/${docsPath}, skipping`);
74+
core.endGroup();
75+
continue;
76+
}
77+
78+
// Read the source repo's docs.json and merge navigation.products
79+
const subConfig = JSON.parse(fs.readFileSync(sourceConfig, 'utf8'));
80+
const subProducts = subConfig.navigation?.products ?? [];
81+
docsConfig.navigation.products.push(...subProducts);
82+
83+
// Copy all content except docs.json and assets/
84+
const copyContents = (src, dest) => {
85+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
86+
if (entry.name === 'docs.json' || entry.name === 'assets') continue;
87+
const srcPath = path.join(src, entry.name);
88+
const destPath = path.join(dest, entry.name);
89+
if (entry.isDirectory()) {
90+
fs.mkdirSync(destPath, { recursive: true });
91+
copyContents(srcPath, destPath);
92+
} else {
93+
fs.cpSync(srcPath, destPath);
94+
}
95+
}
96+
};
97+
98+
copyContents(sourceDir, outDir);
99+
core.endGroup();
100+
}
101+
102+
// Write the merged docs.json
103+
fs.writeFileSync(
104+
path.join(outDir, 'docs.json'),
105+
JSON.stringify(docsConfig, null, 4) + '\n'
106+
);
107+
108+
core.info(`Aggregated ${docsConfig.navigation.products.length} product(s)`);
109+
110+
// Switch to the docs branch and replace contents
111+
const branch = 'docs';
112+
113+
try {
114+
await exec.exec('git', ['fetch', 'origin', branch]);
115+
await exec.exec('git', ['checkout', branch]);
116+
} catch {
117+
await exec.exec('git', ['checkout', '--orphan', branch]);
118+
await exec.exec('git', ['rm', '-rf', '.']);
119+
}
120+
121+
// Clear the working directory (except .git)
122+
for (const entry of fs.readdirSync('.')) {
123+
if (entry === '.git') continue;
124+
await io.rmRF(entry);
125+
}
126+
127+
// Copy aggregated content into the working directory
128+
await io.cp(outDir, '.', { recursive: true, force: true });
129+
130+
// Commit and push
131+
await exec.exec('git', ['add', '.']);
132+
133+
let hasChanges = false;
134+
try {
135+
await exec.exec('git', ['diff', '--cached', '--quiet']);
136+
} catch {
137+
hasChanges = true;
138+
}
139+
140+
if (!hasChanges) {
141+
core.info('No changes detected, skipping commit');
142+
return;
143+
}
144+
145+
await exec.exec('git', ['config', 'user.name', 'github-actions[bot]']);
146+
await exec.exec('git', [
147+
'config', 'user.email',
148+
'github-actions[bot]@users.noreply.github.com'
149+
]);
150+
await exec.exec('git', ['commit', '-m', 'docs: aggregate from source repos']);
151+
await exec.exec('git', ['push', 'origin', branch]);
152+
153+
core.info('Docs aggregated and pushed successfully');

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# CortexPHP Documentation
2+
3+
This is a **read-only** repository for the CortexPHP documentation.
4+
Each component has its own repository, and the documentation is aggregated here.

assets/favicon.svg

Lines changed: 13 additions & 0 deletions
Loading

assets/logo-dark.svg

Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)