Add Agentic Workflows as a new resource type

Add support for contributing Agentic Workflows — AI-powered repository
automations that run coding agents in GitHub Actions, defined in markdown
with natural language instructions (https://github.github.com/gh-aw).

Changes:
- Create workflows/ directory for community-contributed workflows
- Add workflow metadata parsing (yaml-parser.mjs)
- Add workflow README generation (update-readme.mjs, constants.mjs)
- Add workflow data to website generation (generate-website-data.mjs)
- Update README.md, CONTRIBUTING.md, and AGENTS.md with workflow docs,
  contributing guidelines, and code review checklists

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Bruno Borges
2026-02-20 15:28:28 -08:00
parent 7bebd4a385
commit 997d6302bd
9 changed files with 402 additions and 7 deletions

View File

@@ -17,13 +17,15 @@ import {
PLUGINS_DIR,
PROMPTS_DIR,
ROOT_FOLDER,
SKILLS_DIR
SKILLS_DIR,
WORKFLOWS_DIR
} from "./constants.mjs";
import { getGitFileDates } from "./utils/git-dates.mjs";
import {
parseFrontmatter,
parseSkillMetadata,
parseHookMetadata,
parseWorkflowMetadata,
parseYamlFile,
} from "./yaml-parser.mjs";
@@ -192,6 +194,67 @@ function generateHooksData(gitDates) {
};
}
/**
* Generate workflows metadata (folder-based, similar to hooks)
*/
function generateWorkflowsData(gitDates) {
const workflows = [];
if (!fs.existsSync(WORKFLOWS_DIR)) {
return {
items: workflows,
filters: {
triggers: [],
tags: [],
},
};
}
const workflowFolders = fs.readdirSync(WORKFLOWS_DIR).filter((file) => {
const filePath = path.join(WORKFLOWS_DIR, file);
return fs.statSync(filePath).isDirectory();
});
const allTriggers = new Set();
const allTags = new Set();
for (const folder of workflowFolders) {
const workflowPath = path.join(WORKFLOWS_DIR, folder);
const metadata = parseWorkflowMetadata(workflowPath);
if (!metadata) continue;
const relativePath = path
.relative(ROOT_FOLDER, workflowPath)
.replace(/\\/g, "/");
const readmeRelativePath = `${relativePath}/README.md`;
(metadata.triggers || []).forEach((t) => allTriggers.add(t));
(metadata.tags || []).forEach((t) => allTags.add(t));
workflows.push({
id: folder,
title: metadata.name,
description: metadata.description,
triggers: metadata.triggers || [],
tags: metadata.tags || [],
assets: metadata.assets || [],
path: relativePath,
readmeFile: readmeRelativePath,
lastUpdated: gitDates.get(readmeRelativePath) || null,
});
}
const sortedWorkflows = workflows.sort((a, b) => a.title.localeCompare(b.title));
return {
items: sortedWorkflows,
filters: {
triggers: Array.from(allTriggers).sort(),
tags: Array.from(allTags).sort(),
},
};
}
/**
* Generate prompts metadata
*/
@@ -606,6 +669,7 @@ function generateSearchIndex(
prompts,
instructions,
hooks,
workflows,
skills,
plugins
) {
@@ -665,6 +729,20 @@ function generateSearchIndex(
});
}
for (const workflow of workflows) {
index.push({
type: "workflow",
id: workflow.id,
title: workflow.title,
description: workflow.description,
path: workflow.readmeFile,
lastUpdated: workflow.lastUpdated,
searchText: `${workflow.title} ${workflow.description} ${workflow.triggers.join(
" "
)} ${workflow.tags.join(" ")}`.toLowerCase(),
});
}
for (const skill of skills) {
index.push({
type: "skill",
@@ -799,7 +877,7 @@ async function main() {
// Load git dates for all resource files (single efficient git command)
console.log("Loading git history for last updated dates...");
const gitDates = getGitFileDates(
["agents/", "prompts/", "instructions/", "hooks/", "skills/", "plugins/"],
["agents/", "prompts/", "instructions/", "hooks/", "workflows/", "skills/", "plugins/"],
ROOT_FOLDER
);
console.log(`✓ Loaded dates for ${gitDates.size} files\n`);
@@ -817,6 +895,12 @@ async function main() {
`✓ Generated ${hooks.length} hooks (${hooksData.filters.hooks.length} hook types, ${hooksData.filters.tags.length} tags)`
);
const workflowsData = generateWorkflowsData(gitDates);
const workflows = workflowsData.items;
console.log(
`✓ Generated ${workflows.length} workflows (${workflowsData.filters.triggers.length} triggers, ${workflowsData.filters.tags.length} tags)`
);
const promptsData = generatePromptsData(gitDates);
const prompts = promptsData.items;
console.log(
@@ -857,6 +941,7 @@ async function main() {
prompts,
instructions,
hooks,
workflows,
skills,
plugins
);
@@ -873,6 +958,11 @@ async function main() {
JSON.stringify(hooksData, null, 2)
);
fs.writeFileSync(
path.join(WEBSITE_DATA_DIR, "workflows.json"),
JSON.stringify(workflowsData, null, 2)
);
fs.writeFileSync(
path.join(WEBSITE_DATA_DIR, "prompts.json"),
JSON.stringify(promptsData, null, 2)
@@ -917,6 +1007,7 @@ async function main() {
instructions: instructions.length,
skills: skills.length,
hooks: hooks.length,
workflows: workflows.length,
plugins: plugins.length,
tools: tools.length,
samples: samplesData.totalRecipes,