diff --git a/.github/autolabeler-config.json b/.github/autolabeler-config.json index 399004ee..7f577efa 100644 --- a/.github/autolabeler-config.json +++ b/.github/autolabeler-config.json @@ -68,4 +68,5 @@ "excludeGlobs": [] } ] + } diff --git a/.github/changelog-pr-config.json b/.github/changelog-pr-config.json index 56401f4f..833c2b37 100644 --- a/.github/changelog-pr-config.json +++ b/.github/changelog-pr-config.json @@ -7,14 +7,26 @@ "title": "🆕 New Scripts", "labels": ["new script"] }, - { - "title": "🐞 Bug Fixes", - "labels": ["bugfix"] - }, { "title": "✨ New Features", "labels": ["feature"] }, + { + "title": "🚀 Updated Scripts", + "labels": ["update script"], + "subCategories": [ + { + "title": "🐞 Bug Fixes", + "labels": ["bugfix"], + "notes" : [] + }, + { + "title": "General Updates", + "labels": ["general"], + "notes" : [] + } + ] + }, { "title": "🌐 Website", "labels": ["website"] diff --git a/.github/workflows/autolabeler.yml b/.github/workflows/autolabeler.yml index 4e0a0434..f2df791f 100644 --- a/.github/workflows/autolabeler.yml +++ b/.github/workflows/autolabeler.yml @@ -32,8 +32,9 @@ jobs: const autolabelerConfig = JSON.parse(fileContent); const prNumber = context.payload.pull_request.number; - const prBody = context.payload.pull_request.body; - + + const prBody = context.payload.pull_request.body.toLowerCase(); + let labelsToAdd = new Set(); const prListFilesResponse = await github.rest.pulls.listFiles({ @@ -42,14 +43,35 @@ jobs: pull_number: prNumber, }); const prFiles = prListFilesResponse.data; + + const templateLabelMappings = { + "🐞 **bug fix**": "bugfix", + "✨ **new feature**": "feature", + "💥 **breaking change**": "breaking change", + "🆕 **new script**": "new script" + }; + + for (const [checkbox, label] of Object.entries(templateLabelMappings)) { + const escapedCheckbox = checkbox.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); + const regex = new RegExp(`- \\[(x|X)\\]\\s*.*${escapedCheckbox}`, "i"); + const match = prBody.match(regex); + if (match) { + console.log(`Match: ${match}`); + labelsToAdd.add(label); + } + } + if (labelsToAdd.size === 0) { + labelsToAdd.add("general"); + } + // Apply labels based on file changes for (const [label, rules] of Object.entries(autolabelerConfig)) { const shouldAddLabel = prFiles.some((prFile) => { return rules.some((rule) => { const isFileStatusMatch = rule.fileStatus ? rule.fileStatus === prFile.status : true; const isIncludeGlobMatch = rule.includeGlobs.some((glob) => minimatch(prFile.filename, glob)); const isExcludeGlobMatch = rule.excludeGlobs.some((glob) => minimatch(prFile.filename, glob)); - + return isFileStatusMatch && isIncludeGlobMatch && !isExcludeGlobMatch; }); }); diff --git a/.github/workflows/changelog-pr.yml b/.github/workflows/changelog-pr.yml index 58bfd8a4..47f8f221 100644 --- a/.github/workflows/changelog-pr.yml +++ b/.github/workflows/changelog-pr.yml @@ -30,7 +30,6 @@ jobs: - name: Get latest dates in changelog run: | - # Extrahiere die neuesten zwei Daten aus dem Changelog DATES=$(grep -E '^## [0-9]{4}-[0-9]{2}-[0-9]{2}' CHANGELOG.md | head -n 2 | awk '{print $2}') LATEST_DATE=$(echo "$DATES" | sed -n '1p') @@ -55,7 +54,15 @@ jobs: const configPath = path.resolve(process.env.CONFIG_PATH); const fileContent = await fs.readFile(configPath, 'utf-8'); const changelogConfig = JSON.parse(fileContent); - const categorizedPRs = changelogConfig.map(obj => ({ ...obj, notes: [] })); + + const categorizedPRs = changelogConfig.map(obj => ({ + ...obj, + notes: [], + subCategories: obj.subCategories ?? (obj.labels.includes("update script") ? [ + { title: "🐞 Bug Fixes", labels: ["bugfix"] }, + { title: "✨ Feature Updates", labels: ["feature"] } + ] : []) + })); const latestDateInChangelog = new Date(process.env.LATEST_DATE); latestDateInChangelog.setUTCHours(23, 59, 59, 999); @@ -70,29 +77,33 @@ jobs: per_page: 100, }); - pulls.filter(pr => - pr.merged_at && - new Date(pr.merged_at) > latestDateInChangelog && - !pr.labels.some(label => ["invalid", "wontdo", process.env.AUTOMATED_PR_LABEL].includes(label.name.toLowerCase())) + pulls.filter(pr => + pr.merged_at && + new Date(pr.merged_at) > latestDateInChangelog && + !pr.labels.some(label => + ["invalid", "wontdo", process.env.AUTOMATED_PR_LABEL].includes(label.name.toLowerCase()) + ) ).forEach(pr => { + const prLabels = pr.labels.map(label => label.name.toLowerCase()); const prNote = `- ${pr.title} [@${pr.user.login}](https://github.com/${pr.user.login}) ([#${pr.number}](${pr.html_url}))`; - let isCategorized = false; - for (const { labels, notes } of categorizedPRs) { - // If no labels are specified (e.g., "Unlabelled"), assign to this category - if (labels.length === 0 && prLabels.length === 0) { - notes.push(prNote); - isCategorized = true; - break; - } + const updateScriptsCategory = categorizedPRs.find(category => + category.labels.some(label => prLabels.includes(label)) + ); + + if (updateScriptsCategory) { + + const subCategory = updateScriptsCategory.subCategories.find(sub => + sub.labels.some(label => prLabels.includes(label)) + ); + + if (subCategory) { + subCategory.notes.push(prNote); + } else { + updateScriptsCategory.notes.push(prNote); - // If labels are specified, check if PR has ALL required labels - if (labels.length > 0 && labels.every(label => prLabels.includes(label.toLowerCase()))) { - notes.push(prNote); - isCategorized = true; - break; } } @@ -104,9 +115,12 @@ jobs: } } }); + + console.log(JSON.stringify(categorizedPRs, null, 2)); return categorizedPRs; + - name: Update CHANGELOG.md uses: actions/github-script@v7 with: @@ -119,13 +133,32 @@ jobs: const changelogPath = path.resolve('CHANGELOG.md'); const categorizedPRs = ${{ steps.get-categorized-prs.outputs.result }}; - let newReleaseNotes = `## ${today}\n\n### Changes\n\n`; - for (const { title, notes } of categorizedPRs) { - if (notes.length > 0) { - newReleaseNotes += `### ${title}\n\n${notes.join("\n")}\n\n`; - } - } + console.log(JSON.stringify(categorizedPRs, null, 2)); + let newReleaseNotes = `## ${today}\n\n### Changes\n\n`; + for (const { title, notes, subCategories } of categorizedPRs) { + const hasSubcategories = subCategories && subCategories.length > 0; + const hasMainNotes = notes.length > 0; + const hasSubNotes = hasSubcategories && subCategories.some(sub => sub.notes && sub.notes.length > 0); + + if (hasMainNotes || hasSubNotes) { + newReleaseNotes += `### ${title}\n\n`; + } + + if (hasMainNotes) { + newReleaseNotes += `${notes.join("\n")}\n\n`; + } + + if (hasSubcategories) { + for (const { title: subTitle, notes: subNotes } of subCategories) { + if (subNotes && subNotes.length > 0) { + newReleaseNotes += ` #### ${subTitle}\n\n`; + newReleaseNotes += ` ${subNotes.join("\n ")}\n\n`; + } + } + } + } + const changelogContent = await fs.readFile(changelogPath, 'utf-8'); const changelogIncludesTodaysReleaseNotes = changelogContent.includes(`\n## ${today}`);