mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-28 19:49:50 +02:00
chore: sync content to repo
This commit is contained in:
committed by
Kamran Ahmed
parent
91b0a232ab
commit
87280b4c9e
55
.github/workflows/sync-content-to-repo.yml
vendored
Normal file
55
.github/workflows/sync-content-to-repo.yml
vendored
Normal 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.**
|
@@ -29,6 +29,7 @@
|
|||||||
"compress:images": "tsx ./scripts/compress-images.ts",
|
"compress:images": "tsx ./scripts/compress-images.ts",
|
||||||
"generate:roadmap-content-json": "tsx ./scripts/editor-roadmap-content-json.ts",
|
"generate:roadmap-content-json": "tsx ./scripts/editor-roadmap-content-json.ts",
|
||||||
"migrate:editor-roadmaps": "tsx ./scripts/migrate-editor-roadmap.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"
|
"test:e2e": "playwright test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
111
scripts/sync-content-to-repo.ts
Normal file
111
scripts/sync-content-to-repo.ts
Normal 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;
|
||||||
|
}
|
Reference in New Issue
Block a user