Merge pull request #77 from TotalControlAdmin/develop #28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Discord Release Notification | |
| "on": | |
| push: | |
| branches: | |
| - master | |
| paths: | |
| - "versioned_docs/version-3/releases/**.mdx" | |
| jobs: | |
| notify: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 2 | |
| - name: Detect new release files | |
| id: detect | |
| run: | | |
| NEW_FILES=$(git diff --name-status HEAD~1 HEAD -- 'versioned_docs/version-3/releases/*.mdx' | grep '^A' | awk '{print $2}' | grep -v 'index.mdx' || true) | |
| echo "files=$NEW_FILES" >> $GITHUB_OUTPUT | |
| - name: Set up Node.js | |
| if: steps.detect.outputs.files != '' | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| - name: Install gray-matter | |
| if: steps.detect.outputs.files != '' | |
| run: npm install gray-matter | |
| - name: Send Discord notification | |
| if: steps.detect.outputs.files != '' | |
| env: | |
| DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }} | |
| DISCORD_ROLE_ID: ${{ secrets.DISCORD_RELEASE_ROLE_ID }} | |
| NEW_FILES: ${{ steps.detect.outputs.files }} | |
| SITE_URL: https://docs.tcadmin.com | |
| run: | | |
| node << 'EOF' | |
| const fs = require('fs'); | |
| const matter = require('gray-matter'); | |
| (async () => { | |
| const files = process.env.NEW_FILES.trim().split('\n').filter(Boolean); | |
| const webhookUrl = process.env.DISCORD_WEBHOOK; | |
| const roleId = process.env.DISCORD_ROLE_ID; | |
| const siteUrl = process.env.SITE_URL; | |
| for (const file of files) { | |
| const raw = fs.readFileSync(file, 'utf8'); | |
| const { data, content } = matter(raw); | |
| const version = data.sidebar_label ?? file.replace(/.*\//, '').replace(/\.mdx?$/, ''); | |
| const date = data.date ? new Date(data.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) : null; | |
| const slug = file.replace(/.*\//, '').replace(/\.mdx?$/, ''); | |
| const url = `${siteUrl}/3/releases/${slug}`; | |
| // Count new features and bug fixes | |
| const featuresMatch = content.match(/###\s+New Features([\s\S]*?)(?:###|$)/); | |
| const fixesMatch = content.match(/###\s+Bug Fixes([\s\S]*?)(?:###|$)/); | |
| const featureCount = featuresMatch ? (featuresMatch[1].match(/^- /gm) || []).length : 0; | |
| const fixCount = fixesMatch ? (fixesMatch[1].match(/^- /gm) || []).length : 0; | |
| // Auto-generate description from New Features bold items | |
| let description = data.description || ''; | |
| if (!description) { | |
| if (featuresMatch) { | |
| const names = []; | |
| const re = /\*\*([^*]+)\*\*/g; | |
| let m; | |
| while ((m = re.exec(featuresMatch[1])) !== null) { | |
| names.push(m[1]); | |
| if (names.length === 5) break; | |
| } | |
| if (names.length) description = names.join(', ') + (names.length === 5 ? ', and more.' : '.'); | |
| } | |
| } | |
| const fields = []; | |
| if (date) fields.push({ name: 'Release Date', value: date, inline: true }); | |
| if (featureCount > 0) fields.push({ name: 'New Features', value: String(featureCount), inline: true }); | |
| if (fixCount > 0) fields.push({ name: 'Bug Fixes', value: String(fixCount), inline: true }); | |
| fields.push({ name: 'Release Notes', value: `[View full release notes](${url})`, inline: false }); | |
| const embed = { | |
| title: `TCAdmin v3 — New Release: ${version}`, | |
| url, | |
| color: 0x57F287, | |
| description: `A new version of TCAdmin v3 has been released!\n\n${description || 'Check the release notes for details.'}`, | |
| fields, | |
| footer: { text: 'TCAdmin Documentation' }, | |
| timestamp: data.date ? new Date(data.date).toISOString() : new Date().toISOString(), | |
| }; | |
| const body = { | |
| content: roleId ? `<@&${roleId}>` : undefined, | |
| embeds: [embed], | |
| }; | |
| const res = await fetch(webhookUrl, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(body), | |
| }); | |
| if (!res.ok) { | |
| console.error(`Discord webhook failed: ${res.status} ${await res.text()}`); | |
| process.exit(1); | |
| } | |
| console.log(`Notified Discord for ${version}`); | |
| } | |
| })(); | |
| EOF |