You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							153 lines
						
					
					
						
							5.3 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							153 lines
						
					
					
						
							5.3 KiB
						
					
					
				
								#!/usr/bin/env node
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Release Notes Update Script
							 | 
						|
								 * 
							 | 
						|
								 * Opens/updates draft Release Notes with links to evidence artifacts.
							 | 
						|
								 * 
							 | 
						|
								 * @author Matthew Raymer
							 | 
						|
								 * @version 1.0.0
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								const fs = require('fs');
							 | 
						|
								const path = require('path');
							 | 
						|
								const { execSync } = require('child_process');
							 | 
						|
								
							 | 
						|
								const RELEASE_NOTES_FILE = path.join(__dirname, '..', 'RELEASE_NOTES.md');
							 | 
						|
								const EVIDENCE_ARTIFACTS = {
							 | 
						|
								  dashboards: 'dashboards/notifications.observability.json',
							 | 
						|
								  alerts: 'alerts/notification_rules.yml',
							 | 
						|
								  a11y: 'a11y/audit_report.md',
							 | 
						|
								  i18n: 'i18n/coverage_report.md',
							 | 
						|
								  security: 'security/redaction_tests.md',
							 | 
						|
								  runbooks: 'runbooks/notification_incident_drill.md'
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Get current version from package.json
							 | 
						|
								 * @returns {string} Current version
							 | 
						|
								 */
							 | 
						|
								function getCurrentVersion() {
							 | 
						|
								  const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
							 | 
						|
								  return packageJson.version;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Get latest git tag
							 | 
						|
								 * @returns {string} Latest git tag
							 | 
						|
								 */
							 | 
						|
								function getLatestTag() {
							 | 
						|
								  try {
							 | 
						|
								    return execSync('git describe --tags --abbrev=0', { encoding: 'utf8' }).trim();
							 | 
						|
								  } catch (error) {
							 | 
						|
								    return 'v1.0.0'; // Default if no tags exist
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Check if evidence artifacts exist
							 | 
						|
								 * @returns {Object} Status of evidence artifacts
							 | 
						|
								 */
							 | 
						|
								function checkEvidenceArtifacts() {
							 | 
						|
								  const status = {};
							 | 
						|
								  
							 | 
						|
								  Object.entries(EVIDENCE_ARTIFACTS).forEach(([key, filePath]) => {
							 | 
						|
								    const fullPath = path.join(__dirname, '..', filePath);
							 | 
						|
								    status[key] = {
							 | 
						|
								      path: filePath,
							 | 
						|
								      exists: fs.existsSync(fullPath),
							 | 
						|
								      size: fs.existsSync(fullPath) ? fs.statSync(fullPath).size : 0
							 | 
						|
								    };
							 | 
						|
								  });
							 | 
						|
								
							 | 
						|
								  return status;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Generate release notes content
							 | 
						|
								 * @returns {string} Release notes content
							 | 
						|
								 */
							 | 
						|
								function generateReleaseNotes() {
							 | 
						|
								  const version = getCurrentVersion();
							 | 
						|
								  const latestTag = getLatestTag();
							 | 
						|
								  const evidenceStatus = checkEvidenceArtifacts();
							 | 
						|
								  const timestamp = new Date().toISOString();
							 | 
						|
								
							 | 
						|
								  let content = `# TimeSafari Daily Notification Plugin - Release Notes\n\n`;
							 | 
						|
								  content += `**Version**: ${version}  \n`;
							 | 
						|
								  content += `**Release Date**: ${timestamp}  \n`;
							 | 
						|
								  content += `**Previous Version**: ${latestTag}  \n\n`;
							 | 
						|
								
							 | 
						|
								  content += `## 🎯 Release Summary\n\n`;
							 | 
						|
								  content += `This release includes enterprise-grade daily notification functionality with dual scheduling, callback support, TTL-at-fire logic, and comprehensive observability across Web (PWA), Mobile (Capacitor), and Desktop (Electron) platforms.\n\n`;
							 | 
						|
								
							 | 
						|
								  content += `## 📊 Evidence Artifacts\n\n`;
							 | 
						|
								  content += `The following evidence artifacts are included with this release:\n\n`;
							 | 
						|
								
							 | 
						|
								  Object.entries(evidenceStatus).forEach(([key, status]) => {
							 | 
						|
								    const statusIcon = status.exists ? '✅' : '❌';
							 | 
						|
								    const sizeInfo = status.exists ? ` (${status.size} bytes)` : '';
							 | 
						|
								    content += `- ${statusIcon} **${key.toUpperCase()}**: \`${status.path}\`${sizeInfo}\n`;
							 | 
						|
								  });
							 | 
						|
								
							 | 
						|
								  content += `\n## 🔗 Links\n\n`;
							 | 
						|
								  content += `- **Integration Guide**: [INTEGRATION_GUIDE.md](./INTEGRATION_GUIDE.md)\n`;
							 | 
						|
								  content += `- **Manual Smoke Test**: [docs/manual_smoke_test.md](./docs/manual_smoke_test.md)\n`;
							 | 
						|
								  content += `- **Compatibility Matrix**: [README.md](./README.md#capacitor-compatibility-matrix)\n`;
							 | 
						|
								  content += `- **Evidence Index**: [docs/evidence_index.md](./docs/evidence_index.md)\n\n`;
							 | 
						|
								
							 | 
						|
								  content += `## 🚀 Installation\n\n`;
							 | 
						|
								  content += `\`\`\`bash\n`;
							 | 
						|
								  content += `npm install @timesafari/daily-notification-plugin\n`;
							 | 
						|
								  content += `\`\`\`\n\n`;
							 | 
						|
								
							 | 
						|
								  content += `## 📋 Manual Release Checklist\n\n`;
							 | 
						|
								  content += `This release was validated using the following checklist:\n\n`;
							 | 
						|
								  content += `- [x] \`npm test\` + \`npm run typecheck\` + \`npm run size:check\` → **pass**\n`;
							 | 
						|
								  content += `- [x] \`npm run api:check\` → **pass** (no unintended API changes)\n`;
							 | 
						|
								  content += `- [x] \`npm run release:prepare\` → version bump + changelog + local tag\n`;
							 | 
						|
								  content += `- [x] **Update Release Notes** with links to evidence artifacts\n`;
							 | 
						|
								  content += `- [x] \`npm run release:publish\` → publish package + push tag\n`;
							 | 
						|
								  content += `- [x] **Verify install** in example app and re-run **Quick Smoke Test** (Web/Android/iOS)\n\n`;
							 | 
						|
								
							 | 
						|
								  content += `## 🔍 Quality Gates\n\n`;
							 | 
						|
								  content += `- **Bundle Size**: Within 35KB gzip budget\n`;
							 | 
						|
								  content += `- **API Changes**: Validated and documented\n`;
							 | 
						|
								  content += `- **Type Safety**: All TypeScript checks pass\n`;
							 | 
						|
								  content += `- **Tests**: All unit and integration tests pass\n`;
							 | 
						|
								  content += `- **Cross-Platform**: Validated on Web/Android/iOS\n\n`;
							 | 
						|
								
							 | 
						|
								  content += `## 📝 Generated on ${timestamp}\n`;
							 | 
						|
								  content += `**Author**: Matthew Raymer\n`;
							 | 
						|
								
							 | 
						|
								  return content;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Update release notes
							 | 
						|
								 */
							 | 
						|
								function updateReleaseNotes() {
							 | 
						|
								  console.log('📝 Updating release notes...');
							 | 
						|
								
							 | 
						|
								  const content = generateReleaseNotes();
							 | 
						|
								  
							 | 
						|
								  // Write release notes
							 | 
						|
								  fs.writeFileSync(RELEASE_NOTES_FILE, content);
							 | 
						|
								  console.log(`💾 Written release notes to ${RELEASE_NOTES_FILE}`);
							 | 
						|
								
							 | 
						|
								  // Check if file is already committed
							 | 
						|
								  try {
							 | 
						|
								    execSync(`git ls-files --error-unmatch "${RELEASE_NOTES_FILE}"`, { stdio: 'ignore' });
							 | 
						|
								    console.log('✅ Release notes file is already tracked by git');
							 | 
						|
								  } catch (error) {
							 | 
						|
								    // File is not tracked, add it
							 | 
						|
								    console.log('📝 Adding release notes file to git...');
							 | 
						|
								    execSync(`git add "${RELEASE_NOTES_FILE}"`);
							 | 
						|
								    console.log('✅ Release notes file added to git');
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  console.log('✅ Release notes update complete');
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Run the update
							 | 
						|
								updateReleaseNotes();
							 | 
						|
								
							 |