mirror of
https://github.com/github/awesome-copilot.git
synced 2026-04-11 02:35:55 +00:00
Fix broken links beginners cli course sync (#1263)
* chore: publish from staged * Update instructions for converting links from original repo * Correct existing broken links * chore: retrigger ci * cleaning up marerialzed plugins * Fixing clean script to sort out plugin.json file too * Fixing readme * Fixing plugin.json drift * Fixing readme --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Aaron Powell <me@aaron-powell.com>
This commit is contained in:
@@ -2,14 +2,73 @@
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { ROOT_FOLDER } from "./constants.mjs";
|
||||
|
||||
const PLUGINS_DIR = path.join(ROOT_FOLDER, "plugins");
|
||||
const MATERIALIZED_DIRS = ["agents", "commands", "skills"];
|
||||
const MATERIALIZED_SPECS = {
|
||||
agents: {
|
||||
path: "agents",
|
||||
restore(dirPath) {
|
||||
return collectFiles(dirPath).map((relativePath) => `./agents/${relativePath}`);
|
||||
},
|
||||
},
|
||||
commands: {
|
||||
path: "commands",
|
||||
restore(dirPath) {
|
||||
return collectFiles(dirPath).map((relativePath) => `./commands/${relativePath}`);
|
||||
},
|
||||
},
|
||||
skills: {
|
||||
path: "skills",
|
||||
restore(dirPath) {
|
||||
return collectSkillDirectories(dirPath).map((relativePath) => `./skills/${relativePath}/`);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function restoreManifestFromMaterializedFiles(pluginPath) {
|
||||
const pluginJsonPath = path.join(pluginPath, ".github/plugin", "plugin.json");
|
||||
if (!fs.existsSync(pluginJsonPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let plugin;
|
||||
try {
|
||||
plugin = JSON.parse(fs.readFileSync(pluginJsonPath, "utf8"));
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to parse ${pluginJsonPath}: ${error.message}`);
|
||||
}
|
||||
|
||||
let changed = false;
|
||||
for (const [field, spec] of Object.entries(MATERIALIZED_SPECS)) {
|
||||
const materializedPath = path.join(pluginPath, spec.path);
|
||||
if (!fs.existsSync(materializedPath) || !fs.statSync(materializedPath).isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const restored = spec.restore(materializedPath);
|
||||
if (!arraysEqual(plugin[field], restored)) {
|
||||
plugin[field] = restored;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
fs.writeFileSync(pluginJsonPath, JSON.stringify(plugin, null, 2) + "\n", "utf8");
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
function cleanPlugin(pluginPath) {
|
||||
const manifestUpdated = restoreManifestFromMaterializedFiles(pluginPath);
|
||||
if (manifestUpdated) {
|
||||
console.log(` Updated ${path.basename(pluginPath)}/.github/plugin/plugin.json`);
|
||||
}
|
||||
|
||||
let removed = 0;
|
||||
for (const subdir of MATERIALIZED_DIRS) {
|
||||
for (const { path: subdir } of Object.values(MATERIALIZED_SPECS)) {
|
||||
const target = path.join(pluginPath, subdir);
|
||||
if (fs.existsSync(target) && fs.statSync(target).isDirectory()) {
|
||||
const count = countFiles(target);
|
||||
@@ -18,7 +77,8 @@ function cleanPlugin(pluginPath) {
|
||||
console.log(` Removed ${path.basename(pluginPath)}/${subdir}/ (${count} files)`);
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
|
||||
return { removed, manifestUpdated };
|
||||
}
|
||||
|
||||
function countFiles(dir) {
|
||||
@@ -33,6 +93,49 @@ function countFiles(dir) {
|
||||
return count;
|
||||
}
|
||||
|
||||
function collectFiles(dir, rootDir = dir) {
|
||||
const files = [];
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const entryPath = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
files.push(...collectFiles(entryPath, rootDir));
|
||||
} else {
|
||||
files.push(toPosixPath(path.relative(rootDir, entryPath)));
|
||||
}
|
||||
}
|
||||
return files.sort();
|
||||
}
|
||||
|
||||
function collectSkillDirectories(dir, rootDir = dir) {
|
||||
const skillDirs = [];
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (!entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const entryPath = path.join(dir, entry.name);
|
||||
if (fs.existsSync(path.join(entryPath, "SKILL.md"))) {
|
||||
skillDirs.push(toPosixPath(path.relative(rootDir, entryPath)));
|
||||
continue;
|
||||
}
|
||||
|
||||
skillDirs.push(...collectSkillDirectories(entryPath, rootDir));
|
||||
}
|
||||
return skillDirs.sort();
|
||||
}
|
||||
|
||||
function arraysEqual(left, right) {
|
||||
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return left.every((value, index) => value === right[index]);
|
||||
}
|
||||
|
||||
function toPosixPath(filePath) {
|
||||
return filePath.split(path.sep).join("/");
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log("Cleaning materialized files from plugins...\n");
|
||||
|
||||
@@ -47,16 +150,26 @@ function main() {
|
||||
.sort();
|
||||
|
||||
let total = 0;
|
||||
let manifestsUpdated = 0;
|
||||
for (const dirName of pluginDirs) {
|
||||
total += cleanPlugin(path.join(PLUGINS_DIR, dirName));
|
||||
const { removed, manifestUpdated } = cleanPlugin(path.join(PLUGINS_DIR, dirName));
|
||||
total += removed;
|
||||
if (manifestUpdated) {
|
||||
manifestsUpdated++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log();
|
||||
if (total === 0) {
|
||||
if (total === 0 && manifestsUpdated === 0) {
|
||||
console.log("✅ No materialized files found. Plugins are already clean.");
|
||||
} else {
|
||||
console.log(`✅ Removed ${total} materialized file(s) from plugins.`);
|
||||
if (manifestsUpdated > 0) {
|
||||
console.log(`✅ Updated ${manifestsUpdated} plugin manifest(s) with folder trailing slashes.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||
main();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user