1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-08-27 19:20:12 +02:00

chore: sync content to repo

This commit is contained in:
Arik Chakma
2025-08-20 12:19:06 +06:00
committed by Kamran Ahmed
parent 91b0a232ab
commit 87280b4c9e
3 changed files with 167 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
name: Sync Content to Repo
on:
workflow_dispatch:
inputs:
roadmap_slug:
description: "The ID of the roadmap to sync"
required: true
default: "__default__"
jobs:
sync-content:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup pnpm@v9
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false
- name: Setup Node.js Version 20 (LTS)
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install Dependencies and Sync Content
run: |
pnpm install
npm run sync:content-to-repo --roadmap-slug=${{ inputs.roadmap_slug }} --secret=${{ secrets.SYNC_CONTENT_TO_REPO_SECRET }}
- name: Create PR
uses: peter-evans/create-pull-request@v7
with:
delete-branch: false
branch: "chore/sync-content-to-repo"
base: "master"
labels: |
dependencies
automated pr
reviewers: arikchakma
commit-message: "chore: sync content to repo"
title: "Sync Content to Repo - Automated"
body: |
## Sync Content to Repo
> [!IMPORTANT]
> This PR Syncs the Content to the Repo for the Roadmap: ${{ inputs.roadmap_slug }}
>
> Commit: ${{ github.sha }}
> Workflow Path: ${{ github.workflow_ref }}
**Please Review the Changes and Merge the PR if everything is fine.**

View File

@@ -29,6 +29,7 @@
"compress:images": "tsx ./scripts/compress-images.ts",
"generate:roadmap-content-json": "tsx ./scripts/editor-roadmap-content-json.ts",
"migrate:editor-roadmaps": "tsx ./scripts/migrate-editor-roadmap.ts",
"sync:content-to-repo": "tsx ./scripts/sync-content-to-repo.ts",
"test:e2e": "playwright test"
},
"dependencies": {

View File

@@ -0,0 +1,111 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { slugify } from '../src/lib/slugger';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const args = process.argv.slice(2);
const roadmapSlug = args?.[0]?.replace('--roadmap-slug=', '');
const secret = args?.[1]?.replace('--secret=', '');
if (!secret) {
throw new Error('Secret is required');
process.exit(1);
}
if (!roadmapSlug || roadmapSlug === '__default__') {
throw new Error('Roadmap slug is required');
process.exit(1);
}
console.log(`🚀 Starting ${roadmapSlug}`);
export const allowedOfficialRoadmapTopicResourceType = [
'official',
'opensource',
'article',
'course',
'podcast',
'video',
'book',
] as const;
export type AllowedOfficialRoadmapTopicResourceType =
(typeof allowedOfficialRoadmapTopicResourceType)[number];
type OfficialRoadmapTopicResource = {
_id?: string;
type: AllowedOfficialRoadmapTopicResourceType;
title: string;
url: string;
};
export interface OfficialRoadmapTopicContentDocument {
_id?: string;
roadmapSlug: string;
nodeId: string;
title: string;
description: string;
resources: OfficialRoadmapTopicResource[];
createdAt: Date;
updatedAt: Date;
}
export async function roadmapTopics(
roadmapId: string,
secret: string,
): Promise<OfficialRoadmapTopicContentDocument[]> {
const path = `https://api.chit.fun/v1-official-roadmap-topics/${roadmapId}?secret=${secret}`;
const response = await fetch(path);
if (!response.ok) {
throw new Error(`Failed to fetch roadmap topics: ${response.statusText}`);
}
const data = await response.json();
if (data.error) {
throw new Error(`Failed to fetch roadmap topics: ${data.error}`);
}
return data;
}
// Directory containing the roadmaps
const ROADMAP_CONTENT_DIR = path.join(
__dirname,
'../src/data/roadmaps',
roadmapSlug,
);
const allTopics = await roadmapTopics(roadmapSlug, secret);
for (const topic of allTopics) {
const { title, nodeId } = topic;
const topicSlug = `${slugify(title)}@${nodeId}.md`;
const topicPath = path.join(ROADMAP_CONTENT_DIR, topicSlug);
const topicDir = path.dirname(topicPath);
const topicDirExists = await fs
.stat(topicDir)
.then(() => true)
.catch(() => false);
if (!topicDirExists) {
await fs.mkdir(topicDir, { recursive: true });
}
const topicContent = prepareTopicContent(topic);
await fs.writeFile(topicPath, topicContent);
console.log(`✅ Synced ${topicSlug}`);
}
function prepareTopicContent(topic: OfficialRoadmapTopicContentDocument) {
const { description, resources = [] } = topic;
const content = `
${description}
Visit the following resources to learn more:
${resources.map((resource) => `- [@${resource.type}@${resource.title}](${resource.url})`).join('\n')}
`.trim();
return content;
}