Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changelog.features.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"features": [
{
"tag": "ACSS",
"description": "Add support for ACSS payments in Canada",
"type": "Local payment method"
},
{
"tag": "Amazon Pay",
"description": "Add support for Amazon Pay to express checkout",
"type": "Express checkout"
},
{
"tag": "BECS",
"description": "Add support for BECS Direct Debits in Australia",
"type": "Local payment method"
},
{
"tag": "BLIK",
"description": "Add support for BLIK payments in Poland",
"type": "Local payment method"
},
{
"tag": "Settings Sync",
"description": "Synchronize payment method settings with Stripe dashboard"
},
{
"tag": "Smart Checkout",
"description": "Add support for Smart Checkout/ Dynamic Payment Element"
}
]
}
71 changes: 64 additions & 7 deletions bin/changelog.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,31 @@ async function findUpcomingVersionSection(content) {
throw new Error('Could not find upcoming version section (xxxx-xx-xx)');
}

async function insertChangelogEntry(filePath, entry) {
async function insertChangelogEntry(filePath, entry, feature) {
try {
const content = await fs.readFile(filePath, 'utf8');
const lines = content.split('\n');
const { startLine, endLine } = await findUpcomingVersionSection(content);


const featurePrefix = feature ? `* [${feature.tag}] ` : null;
// Find the last entry in the current version section
// If we have a feature tag, track the last line with that tag
let insertPosition = startLine + 1;
let lastFeatureTagLine = null;
for (let i = startLine + 1; i <= endLine; i++) {
if (lines[i].trim().startsWith('*')) {
const currentLine = lines[i].trim();
if (currentLine.startsWith('*')) {
if (featurePrefix && currentLine.startsWith(featurePrefix)) {
lastFeatureTagLine = i;
}
insertPosition = i + 1;
}
}


if ( lastFeatureTagLine ) {
insertPosition = lastFeatureTagLine + 1;
}

// Insert the new entry after the last existing entry
lines.splice(insertPosition, 0, entry);

Expand All @@ -51,6 +62,22 @@ async function insertChangelogEntry(filePath, entry) {
}
}

async function getChangelogFeatures() {
try {
const featureFileContents = await fs.readFile('.changelog.features.json', 'utf8');
const featureFileJSON = JSON.parse(featureFileContents);
if ( Array.isArray(featureFileJSON.features) ) {
// Require a tag and description for each feature
return featureFileJSON.features.filter(feature => feature.tag && feature.description);
}

// If
throw new Error('Invalid features array in .changelog.features.json');
} catch (error) {
throw new Error(`Failed to read .changelog.features.json: ${error.message}`);
}
}

async function main() {
try {
// Prepare type choices for inquirer
Expand All @@ -59,6 +86,18 @@ async function main() {
value: type
}));

const rawFeatures = await getChangelogFeatures();
const features = rawFeatures.map(feature => ({
name: `[${feature.tag}] - ${feature.description}` + (feature.type ? ` (${feature.type})` : ''),
value: feature,
}));

// Ensure we have an escape hatch!
features.unshift({
name: '\u001B[3mNever mind (No feature)\u001B[23m', // Escape sequences start and stop italics
value: null,
});

// Get user input
const answers = await inquirer.prompt([
{
Expand All @@ -72,15 +111,33 @@ async function main() {
name: 'message',
message: 'Enter the changelog message:',
validate: input => input.trim().length > 0 || 'Message cannot be empty'
},
{
type: 'confirm',
name: 'isForFeature',
message: 'Is this change for a feature?',
default: false
},
]);

const featureAnswer = !answers.isForFeature ? null : await inquirer.prompt([
{
type: 'list',
name: 'feature',
message: 'Select the feature:',
choices: features,
default: 0,
}
]);
const feature = featureAnswer?.feature ?? null;

const entryPrefix = '* ' + (feature ? `[${feature.tag}] ` : '');
const entry = `${entryPrefix}${answers.changeType} - ${answers.message.trim()}`;

const entry = `* ${answers.changeType} - ${answers.message.trim()}`;

// Update both files
const files = ['changelog.txt', 'readme.txt'];
for (const file of files) {
await insertChangelogEntry(file, entry);
await insertChangelogEntry(file, entry, feature);
}

console.log('✅ Changelog entries added successfully to changelog.txt and readme.txt');
Expand Down
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* Dev - Improve SPE e2e tests to reduce flakiness
* Fix - Prevents fatal errors for cases where we fail to load product details
* Fix - Address an edge case with webhook URL comparisons
* Tweak - Add feature support to the changelog tool

= 9.4.1 - 2025-04-17 =
* Dev - Forces rollback of version 9.4.0.
Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,6 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
* Dev - Improve SPE e2e tests to reduce flakiness
* Fix - Prevents fatal errors for cases where we fail to load product details
* Fix - Address an edge case with webhook URL comparisons
* Tweak - Add feature support to the changelog tool

[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce-gateway-stripe/trunk/changelog.txt).
Loading