From 1e6327b0280c0df8621f66fbaba7d28d95ff224a Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Thu, 13 Mar 2025 22:05:21 -0400 Subject: [PATCH 1/2] Add script to update a Contributors section in the README --- README.md | 24 ++++ package.json | 3 +- scripts/update-contributors.js | 208 +++++++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+), 1 deletion(-) create mode 100755 scripts/update-contributors.js diff --git a/README.md b/README.md index f907ea480ee..0dc8c068987 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,30 @@ We love community contributions! Here’s how to get involved: --- + + +## Contributors + +Thanks to all our contributors who have helped make Roo Code better! + +| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| a8trejo
a8trejo
| +| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| ColemanRoo
ColemanRoo
| stea9499
stea9499
| joemanley201
joemanley201
| System233
System233
| jquanton
jquanton
| nissa-seru
nissa-seru
| +| hannesrudolph
hannesrudolph
| MuriloFP
MuriloFP
| NyxJae
NyxJae
| punkpeye
punkpeye
| d-oit
d-oit
| monotykamary
monotykamary
| +| lloydchang
lloydchang
| vigneshsubbiah16
vigneshsubbiah16
| Szpadel
Szpadel
| lupuletic
lupuletic
| cannuri
cannuri
| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| +| Premshay
Premshay
| psv2522
psv2522
| olweraltuve
olweraltuve
| RaySinner
RaySinner
| qdaxb
qdaxb
| afshawnlotfi
afshawnlotfi
| +| emshvac
emshvac
| Lunchb0ne
Lunchb0ne
| sammcj
sammcj
| dtrugman
dtrugman
| aitoroses
aitoroses
| yt3trees
yt3trees
| +| yongjer
yongjer
| vincentsong
vincentsong
| pugazhendhi-m
pugazhendhi-m
| eonghk
eonghk
| philfung
philfung
| pdecat
pdecat
| +| napter
napter
| mdp
mdp
| jcbdev
jcbdev
| anton-otee
anton-otee
| AMHesch
AMHesch
| bannzai
bannzai
| +| dairui1
dairui1
| dqroid
dqroid
| kinandan
kinandan
| kohii
kohii
| lightrabbit
lightrabbit
| olup
olup
| +| moqimoqidea
moqimoqidea
| mosleyit
mosleyit
| oprstchn
oprstchn
| philipnext
philipnext
| refactorthis
refactorthis
| samir-nimbly
samir-nimbly
| +| shaybc
shaybc
| shohei-ihaya
shohei-ihaya
| student20880
student20880
| PretzelVector
PretzelVector
| adamwlarson
adamwlarson
| alarno
alarno
| +| andreastempsch
andreastempsch
| Atlogit
Atlogit
| dleen
dleen
| dbasclpy
dbasclpy
| celestial-vault
celestial-vault
| DeXtroTip
DeXtroTip
| +| hesara
hesara
| eltociear
eltociear
| libertyteeth
libertyteeth
| mamertofabian
mamertofabian
| marvijo-code
marvijo-code
| Sarke
Sarke
| +| tgfjt
tgfjt
| vladstudio
vladstudio
| ashktn
ashktn
| | | | + + + ## License [Apache 2.0 © 2025 Roo Veterinary, Inc.](./LICENSE) diff --git a/package.json b/package.json index 3cfe3dee28a..bf397d5351b 100644 --- a/package.json +++ b/package.json @@ -307,7 +307,8 @@ "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", "watch-tests": "tsc -p . -w --outDir out", "changeset": "changeset", - "knip": "knip --include files" + "knip": "knip --include files", + "update-contributors": "node scripts/update-contributors.js" }, "dependencies": { "@anthropic-ai/bedrock-sdk": "^0.10.2", diff --git a/scripts/update-contributors.js b/scripts/update-contributors.js new file mode 100755 index 00000000000..cc211410006 --- /dev/null +++ b/scripts/update-contributors.js @@ -0,0 +1,208 @@ +#!/usr/bin/env node + +/** + * This script fetches contributor data from GitHub and updates the README.md file + * with a contributors section showing avatars and usernames. + */ + +const https = require("https") +const fs = require("fs") +const path = require("path") + +// GitHub API URL for fetching contributors +const GITHUB_API_URL = "https://api.github.com/repos/RooVetGit/Roo-Code/contributors?per_page=100" +const README_PATH = path.join(__dirname, "..", "README.md") + +// Sentinel markers for contributors section +const START_MARKER = "" +const END_MARKER = "" + +// HTTP options for GitHub API request +const options = { + headers: { + "User-Agent": "Roo-Code-Contributors-Script", + }, +} + +// Add GitHub token for authentication if available +if (process.env.GITHUB_TOKEN) { + options.headers.Authorization = `token ${process.env.GITHUB_TOKEN}` + console.log("Using GitHub token from environment variable") +} + +/** + * Fetches contributors data from GitHub API + * @returns {Promise} Array of contributor objects + */ +function fetchContributors() { + return new Promise((resolve, reject) => { + https + .get(GITHUB_API_URL, options, (res) => { + if (res.statusCode !== 200) { + reject(new Error(`GitHub API request failed with status code: ${res.statusCode}`)) + return + } + + let data = "" + res.on("data", (chunk) => { + data += chunk + }) + + res.on("end", () => { + try { + const contributors = JSON.parse(data) + resolve(contributors) + } catch (error) { + reject(new Error(`Failed to parse GitHub API response: ${error.message}`)) + } + }) + }) + .on("error", (error) => { + reject(new Error(`GitHub API request failed: ${error.message}`)) + }) + }) +} + +/** + * Reads the README.md file + * @returns {Promise} README content + */ +function readReadme() { + return new Promise((resolve, reject) => { + fs.readFile(README_PATH, "utf8", (err, data) => { + if (err) { + reject(new Error(`Failed to read README.md: ${err.message}`)) + return + } + resolve(data) + }) + }) +} + +/** + * Creates HTML for the contributors section + * @param {Array} contributors Array of contributor objects from GitHub API + * @returns {string} HTML for contributors section + */ +function formatContributorsSection(contributors) { + // Filter out GitHub Actions bot + const filteredContributors = contributors.filter((c) => !c.login.includes("[bot]") && !c.login.includes("R00-B0T")) + + // Start building with Markdown table format + let markdown = `${START_MARKER} +## Contributors + +Thanks to all our contributors who have helped make Roo Code better! + +` + // Number of columns in the table + const COLUMNS = 6 + + // Create contributor cell HTML + const createCell = (contributor) => { + return `${contributor.login}
${contributor.login}
` + } + + if (filteredContributors.length > 0) { + // Table header is the first row of contributors + const headerCells = filteredContributors.slice(0, COLUMNS).map(createCell) + + // Fill any empty cells in header row + while (headerCells.length < COLUMNS) { + headerCells.push(" ") + } + + // Add header row + markdown += `|${headerCells.join("|")}|\n` + + // Add alignment row + markdown += "|" + for (let i = 0; i < COLUMNS; i++) { + markdown += ":---:|" + } + markdown += "\n" + + // Add remaining contributor rows starting with the second batch + for (let i = COLUMNS; i < filteredContributors.length; i += COLUMNS) { + const rowContributors = filteredContributors.slice(i, i + COLUMNS) + + // Create cells for each contributor in this row + const cells = rowContributors.map(createCell) + + // Fill any empty cells to maintain table structure + while (cells.length < COLUMNS) { + cells.push(" ") + } + + // Add row to the table + markdown += `|${cells.join("|")}|\n` + } + } + + markdown += `${END_MARKER}` + return markdown +} + +/** + * Updates the README.md file with contributors section + * @param {string} readmeContent Original README content + * @param {string} contributorsSection HTML for contributors section + * @returns {Promise} + */ +function updateReadme(readmeContent, contributorsSection) { + // Find existing contributors section markers + const startPos = readmeContent.indexOf(START_MARKER) + const endPos = readmeContent.indexOf(END_MARKER) + + if (startPos === -1 || endPos === -1) { + console.warn("Warning: Could not find contributors section markers in README.md") + console.warn("Skipping update - please add markers to enable automatic updates.") + return + } + + // Replace existing section, trimming whitespace at section boundaries + const beforeSection = readmeContent.substring(0, startPos).trimEnd() + const afterSection = readmeContent.substring(endPos + END_MARKER.length).trimStart() + // Ensure single newline separators between sections + const updatedContent = beforeSection + "\n\n" + contributorsSection.trim() + "\n\n" + afterSection + + return writeReadme(updatedContent) +} + +/** + * Writes updated content to README.md + * @param {string} content Updated README content + * @returns {Promise} + */ +function writeReadme(content) { + return new Promise((resolve, reject) => { + fs.writeFile(README_PATH, content, "utf8", (err) => { + if (err) { + reject(new Error(`Failed to write updated README.md: ${err.message}`)) + return + } + resolve() + }) + }) +} + +/** + * Main function that orchestrates the update process + */ +async function main() { + try { + const contributors = await fetchContributors() + + const readmeContent = await readReadme() + + const contributorsSection = formatContributorsSection(contributors) + + await updateReadme(readmeContent, contributorsSection) + } catch (error) { + console.error(`Error: ${error.message}`) + process.exit(1) + } +} + +// Run the script +main() From e068bd6a967b3b21430211eaf9d94c0b95fd985b Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Thu, 13 Mar 2025 22:06:58 -0400 Subject: [PATCH 2/2] Add CI step to update contributors --- .github/workflows/update-contributors.yml | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/update-contributors.yml diff --git a/.github/workflows/update-contributors.yml b/.github/workflows/update-contributors.yml new file mode 100644 index 00000000000..a83a8048072 --- /dev/null +++ b/.github/workflows/update-contributors.yml @@ -0,0 +1,48 @@ +name: Update Contributors + +on: + push: + branches: + - main + workflow_dispatch: # Allows manual triggering + +jobs: + update-contributors: + runs-on: ubuntu-latest + permissions: + contents: write # Needed for pushing changes + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Update contributors + run: npm run update-contributors + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check for changes + id: check-changes + run: | + if [[ -n "$(git status --porcelain README.md)" ]]; then + echo "changes=true" >> $GITHUB_OUTPUT + else + echo "No changes to README.md" + fi + + - name: Commit and push changes + if: steps.check-changes.outputs.changes == 'true' + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add README.md + git commit -m "docs: update contributors list [skip ci]" + git push \ No newline at end of file