Implement PR-based changelog automation and sync roadmap with active development #66

Merged
Copilot merged 19 commits from copilot/update-roadmap-xirrent-prs into copilot/generate-version-specific-roadmap 2026-01-28 11:13:57 +00:00
2 changed files with 206 additions and 0 deletions
Showing only changes of commit a36552d11e - Show all commits

View File

@@ -0,0 +1,194 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# This file is part of a Moko Consulting project.
#
# SPDX-License-Identifier: GPL-3.0-or-later
name: Changelog Validation
on:
pull_request:
types: [opened, edited, synchronize, reopened]
branches:
- main
- 'dev/**'
- 'rc/**'
- 'version/**'
permissions:
contents: read
pull-requests: write
jobs:
validate-changelog-entry:
name: Validate Changelog Entry
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changelog entry in PR description
id: check_changelog
uses: actions/github-script@v7
with:
script: |
const prBody = context.payload.pull_request.body || '';
const prNumber = context.payload.pull_request.number;
const prAuthor = context.payload.pull_request.user.login;
// Skip for automated PRs (e.g., Dependabot)
const automatedAuthors = ['dependabot[bot]', 'github-actions[bot]'];
if (automatedAuthors.includes(prAuthor)) {
console.log('Skipping changelog check for automated PR');
core.setOutput('has_entry', 'true');
core.setOutput('skip', 'true');
return;
}
// Check if PR body contains changelog entry section
const changelogSection = prBody.match(/## Changelog Entry[\s\S]*?```markdown([\s\S]*?)```/);
if (!changelogSection) {
console.log('No changelog entry section found in PR template');
core.setOutput('has_entry', 'false');
core.setOutput('skip', 'false');
return;
}
const changelogContent = changelogSection[1].trim();
// Check if changelog entry is not just the template placeholder
const isPlaceholder = changelogContent.includes('[Category]') ||
changelogContent.includes('Your changelog entry here') ||
changelogContent.length < 20;
if (isPlaceholder) {
console.log('Changelog entry appears to be placeholder text');
core.setOutput('has_entry', 'false');
core.setOutput('skip', 'false');
return;
}
// Validate that it contains a category
const validCategories = ['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security'];
const hasValidCategory = validCategories.some(cat => changelogContent.includes(`### ${cat}`));
if (!hasValidCategory) {
console.log('Changelog entry does not contain a valid category');
core.setOutput('has_entry', 'false');
core.setOutput('skip', 'false');
core.setOutput('reason', 'missing_category');
return;
}
console.log('Valid changelog entry found');
core.setOutput('has_entry', 'true');
core.setOutput('skip', 'false');
core.setOutput('entry', changelogContent);
- name: Comment on PR if changelog entry is missing
if: steps.check_changelog.outputs.has_entry == 'false' && steps.check_changelog.outputs.skip == 'false'
uses: actions/github-script@v7
with:
script: |
const reason = '${{ steps.check_changelog.outputs.reason }}';
let message = '## ⚠️ Changelog Entry Required\n\n';
if (reason === 'missing_category') {
message += 'Your PR includes a changelog entry, but it does not contain a valid category.\n\n';
} else {
message += 'This PR is missing a changelog entry or contains only placeholder text.\n\n';
}
message += 'Please add a changelog entry in the "Changelog Entry" section of the PR description.\n\n';
message += '### Valid Categories\n';
message += '- **Added** - New features or files\n';
message += '- **Changed** - Modifications to existing functionality\n';
message += '- **Deprecated** - Features marked for future removal\n';
message += '- **Removed** - Deleted features or files\n';
message += '- **Fixed** - Bug fixes\n';
message += '- **Security** - Security-related changes\n\n';
message += '### Example\n';
message += '```markdown\n';
message += '### Added\n';
message += '- New feature description (#' + context.payload.pull_request.number + ')\n\n';
message += '### Changed\n';
message += '- Modified behavior description (#' + context.payload.pull_request.number + ')\n';
message += '```\n\n';
message += 'See [CHANGELOG_PROCESS.md](https://github.com/mokoconsulting-tech/moko-cassiopeia/blob/main/docs/CHANGELOG_PROCESS.md) for detailed guidelines.';
// Check if we already commented
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number
});
const botComment = comments.data.find(comment =>
comment.user.login === 'github-actions[bot]' &&
comment.body.includes('Changelog Entry Required')
);
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: message
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: message
});
}
- name: Add label if changelog is missing
if: steps.check_changelog.outputs.has_entry == 'false' && steps.check_changelog.outputs.skip == 'false'
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: ['needs-changelog']
});
- name: Remove label if changelog is present
if: steps.check_changelog.outputs.has_entry == 'true' && steps.check_changelog.outputs.skip == 'false'
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
name: 'needs-changelog'
});
} catch (error) {
// Label might not exist, that's okay
console.log('Label does not exist or already removed');
}
- name: Set status
if: steps.check_changelog.outputs.skip == 'false'
run: |
if [ "${{ steps.check_changelog.outputs.has_entry }}" == "true" ]; then
echo "✅ Changelog entry found and validated"
exit 0
else
echo "❌ Changelog entry is missing or invalid"
echo "Please add a changelog entry to your PR description"
exit 1
fi

View File

@@ -14,6 +14,18 @@
# Changelog — Moko-Cassiopeia (VERSION: 03.06.00) # Changelog — Moko-Cassiopeia (VERSION: 03.06.00)
## [Unreleased]
### Added
- PR-based changelog process with comprehensive documentation (#66)
- Created CHANGELOG_PROCESS.md guide with detailed workflow
- Added changelog entry section to PR template
- Integrated changelog guidance into CONTRIBUTING.md and WORKFLOW_GUIDE.md
### Changed
- Updated roadmap documentation based on current open pull requests (#66)
- Added document generation system as planned feature (#66)
- Synchronized roadmap version timeline with active development branches (#66)
## [03.06.00] 2026-01-28 ## [03.06.00] 2026-01-28
### Changed ### Changed
- Updated version to 03.06.00 across all files - Updated version to 03.06.00 across all files