-
Notifications
You must be signed in to change notification settings - Fork 605
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: Automated changelogs from beamer (#7593)
* beamer first pass * add beamer fetcher * add github action * revert old gha * revert konnet changelog * beamer updates towards wireframe * place holder badge styling * caps * first pass at trying out styling * try some badges * Remove date writing, add compromise library * change the way badges are written so we can render multiple badges on the same line * final styling * remove compromise library add new tagging system in beamer * reset changelog * Update fetch-konnect-changelog.yml * reset badges --------- Co-authored-by: Lena <[email protected]>
- Loading branch information
1 parent
0a56e3d
commit b3b60c3
Showing
4 changed files
with
209 additions
and
27 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
name: Update Konnect Changelog | ||
|
||
on: workflow_dispatch | ||
|
||
concurrency: | ||
cancel-in-progress: true | ||
group: ${{ github.workflow }} | ||
|
||
permissions: | ||
contents: write | ||
pull-requests: write | ||
|
||
jobs: | ||
update-changelog: | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 10 | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
token: ${{ secrets.PAT }} | ||
- name: Run changelog script | ||
working-directory: tools/beamer | ||
env: | ||
BEAMER_API_KEY: ${{ secrets.BEAMER_API_KEY }} | ||
run: | | ||
npm ci | ||
node fetch-beamer-posts.js | ||
- name: Create Pull Request | ||
uses: peter-evans/create-pull-request@v6 | ||
with: | ||
title: Automated Konnect changelog update [skip-ci] | ||
body: | | ||
Latest Konnect changelog entries from beamer | ||
labels: skip-changelog,review:general | ||
base: main | ||
branch: automated-konnect-changelog-update | ||
token: ${{ secrets.PAT }} | ||
committer: kong-docs[bot] <[email protected]> | ||
author: kong-docs[bot] <[email protected]> | ||
delete-branch: true | ||
commit-message: "Automated Konnect changelog update" |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,4 +41,4 @@ jobs: | |
committer: kong-docs[bot] <[email protected]> | ||
author: kong-docs[bot] <[email protected]> | ||
delete-branch: true | ||
commit-message: "Automated changelog update" | ||
commit-message: "Automated changelog update" |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,30 @@ | ||
.page-changelog { | ||
.version-select { | ||
ul { | ||
li { | ||
a { | ||
display: flex; | ||
align-items: center; | ||
justify-content: left; | ||
} | ||
&.active { | ||
a { | ||
color: @blue; | ||
} | ||
} | ||
} | ||
} | ||
.changelog-entries { | ||
display: flex; | ||
flex-direction: row; | ||
margin-bottom: 25px; | ||
|
||
.changelog-date { | ||
display: block; | ||
font-weight: 200; | ||
font-size: 18px; | ||
} | ||
|
||
.content { | ||
h2 { | ||
margin-top: none; | ||
.changelog-entry { | ||
flex-direction: column; | ||
margin-left: 35px; | ||
|
||
.changelog-title { | ||
display: inline-block; | ||
font-weight: 600; | ||
font-size: 18px; | ||
} | ||
ul { | ||
margin-left: 1.5rem; | ||
font-size: 100%; | ||
|
||
li { | ||
margin-bottom: 2rem; | ||
} | ||
.changelog-description { | ||
margin-top: 8px; | ||
|
||
} | ||
.changelog-badges { | ||
margin-top: 8px; | ||
} | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
const https = require('https'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const apiKey = process.env.BEAMER_API_KEY; | ||
// const filePath = process.env.FILE_PATH; | ||
const filePath = __dirname + "/../../app/konnect/updates.md"; | ||
const options = { | ||
hostname: 'api.getbeamer.com', | ||
port: 443, | ||
path: '/v0/posts', | ||
method: 'GET', | ||
headers: { | ||
'Beamer-Api-Key': apiKey, | ||
} | ||
}; | ||
const monthNames = [ | ||
"January", "February", "March", "April", "May", "June", | ||
"July", "August", "September", "October", "November", "December" | ||
]; | ||
|
||
function cleanHTML(contentHtml) { | ||
if (!contentHtml) return ''; | ||
return contentHtml | ||
.replace(/<[^>]*>/g, '') // Remove HTML tags | ||
.replace(/\s+/g, ' ') // Replace multiple spaces/newlines with a single space | ||
.trim(); // Trim leading and trailing spaces | ||
} | ||
|
||
// Function to summarize content by extracting the first two sentences | ||
function summarizeContent(content, maxSentences = 2) { | ||
const sentenceRegex = /[^.!?]*[.!?]/g; // Regex to capture sentences | ||
const sentences = content.match(sentenceRegex) || []; // Match all sentences in the content | ||
|
||
// Extract and join the first 'maxSentences' sentences | ||
const summary = sentences.slice(0, maxSentences).join(' ').trim(); | ||
return summary; | ||
} | ||
|
||
// Function to clean and summarize content | ||
function cleanContent(content) { | ||
const cleanedContent = content.replace(/\s+/g, ' ').trim(); | ||
return summarizeContent(cleanedContent); // Summarize the cleaned content | ||
} | ||
|
||
const req = https.request(options, (res) => { | ||
let data = ''; | ||
|
||
res.on('data', (chunk) => { | ||
data += chunk; | ||
}); | ||
|
||
res.on('end', () => { | ||
try { | ||
const posts = JSON.parse(data); | ||
const groupedPosts = {}; | ||
|
||
posts.forEach(post => { | ||
const date = new Date(post.date); | ||
const month = monthNames[date.getMonth()]; | ||
const year = date.getFullYear(); | ||
const day = String(date.getDate()).padStart(2, '0'); | ||
const monthYear = `${month} ${year}`; | ||
const formattedDate = `${month} ${day}`; | ||
|
||
if (!groupedPosts[monthYear]) { | ||
groupedPosts[monthYear] = []; | ||
} | ||
|
||
post.translations.forEach(translation => { | ||
// Check if 'changelog' is part of the category | ||
if (translation.category.split(';').some(cat => cat.trim().toLowerCase() === 'changelog')) { | ||
let contentPreview = translation.content ? cleanContent(translation.content) : cleanHTML(translation.contentHtml); | ||
groupedPosts[monthYear].push({ | ||
date: formattedDate, | ||
title: translation.title, | ||
postUrl: translation.postUrl, | ||
content: contentPreview, | ||
}); | ||
} | ||
}); | ||
}); | ||
|
||
let updatesContent = ''; | ||
|
||
for (const [monthYear, posts] of Object.entries(groupedPosts)) { | ||
// Add the month and year heading before the posts for that month | ||
updatesContent += `## ${monthYear}\n\n`; | ||
|
||
posts.forEach(post => { | ||
updatesContent += `<div class="changelog-entries">\n`; | ||
updatesContent += `<div class="changelog-date">${post.date}</div>\n`; | ||
updatesContent += `<div class="changelog-entry">\n`; | ||
updatesContent += `<div class="changelog-title">\n`; | ||
updatesContent += `<a href="${post.postUrl}">${post.title}</a>\n`; | ||
updatesContent += `</div>\n`; | ||
|
||
if (post.content) { | ||
updatesContent += `<div class="changelog-description">${post.content}</div>\n`; | ||
} | ||
|
||
updatesContent += `</div>\n`; | ||
updatesContent += `</div>\n`; | ||
}); | ||
} | ||
|
||
fs.readFile(filePath, 'utf8', (err, data) => { | ||
if (err) { | ||
console.error('Error reading file:', err); | ||
return; | ||
} | ||
|
||
const match = data.match(/## \w+ \d{4}/); | ||
if (!match) { | ||
console.error('First month heading not found in file.'); | ||
return; | ||
} | ||
const insertIndex = match.index; | ||
|
||
const newContent = `${data.slice(0, insertIndex)}${updatesContent}\n${data.slice(insertIndex)}`; | ||
|
||
fs.writeFile(filePath, newContent, 'utf8', (err) => { | ||
if (err) { | ||
console.error('Error writing to file:', err); | ||
return; | ||
} | ||
|
||
console.log('Updates added successfully!'); | ||
}); | ||
}); | ||
} catch (error) { | ||
console.error('Error parsing response:', error); | ||
} | ||
}); | ||
}); | ||
|
||
req.on('error', (e) => { | ||
console.error('Error making request:', e); | ||
}); | ||
|
||
req.end(); |