Skip to content

Added Migrate SDM to EDM skill for migration#109

Open
ashwani123p wants to merge 2 commits intomainfrom
users/ashwanikumar/migrate-sdm-to-edm-skill
Open

Added Migrate SDM to EDM skill for migration#109
ashwani123p wants to merge 2 commits intomainfrom
users/ashwanikumar/migrate-sdm-to-edm-skill

Conversation

@ashwani123p
Copy link
Copy Markdown

No description provided.

@ashwani123p ashwani123p requested a review from a team as a code owner April 20, 2026 10:01
Copilot AI review requested due to automatic review settings April 20, 2026 10:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Power Pages skill (migrate-sdm-to-edm) to guide SDM→EDM migrations via PAC CLI, including HTML report templates and a Node utility to generate those reports.

Changes:

  • Introduces the migrate-sdm-to-edm skill workflow (SKILL.md) and accompanying design/integration docs.
  • Adds HTML templates for customization and execution reporting.
  • Adds a Node script to generate the HTML reports and registers the skill in skill-tracking mapping.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
plugins/power-pages/skills/migrate-sdm-to-edm/scripts/generate-migration-reports.js New CLI utility that parses PAC CSV output and renders HTML reports from templates
plugins/power-pages/skills/migrate-sdm-to-edm/assets/skill-execution-report.html New execution report HTML template with placeholders
plugins/power-pages/skills/migrate-sdm-to-edm/assets/customization-report.html New customization report HTML template with placeholders
plugins/power-pages/skills/migrate-sdm-to-edm/assets/README.md Documents template placeholders and intended usage
plugins/power-pages/skills/migrate-sdm-to-edm/SKILL.md New skill definition and phased migration guidance
plugins/power-pages/skills/migrate-sdm-to-edm/REPORTS_INTEGRATION.md Integration guidance for generating and sharing reports in the workflow
plugins/power-pages/skills/migrate-sdm-to-edm/DESIGN.md Design/spec for the migration skill
plugins/power-pages/references/skill-tracking-reference.md Adds the new skill to the skill-name mapping table

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +18 to +21
const fs = require('fs');
const path = require('path');
const { parse: parseCSV } = require('csv-parse/sync');

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

csv-parse/sync is required here, but there’s no csv-parse dependency anywhere in this repo (no package.json / lockfile references). As-is, running this script will fail with "Cannot find module 'csv-parse/sync'". Either add the dependency in the repo’s Node dependency manifest (and ensure install in the workflow) or replace this with a zero-dependency CSV parser appropriate for the PAC output.

Copilot uses AI. Check for mistakes.
.replace('{{WEBSITE_ID}}', escapeHtml(args['website-id'] || 'N/A'))
.replace('{{PORTAL_ID}}', escapeHtml(args['portal-id'] || 'N/A'))
.replace('{{MIGRATION_STATUS_TEXT}}', 'Completed Successfully')
.replace('{{REPORT_DATE}}', dateStr)
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue here: {{REPORT_DATE}} occurs twice in skill-execution-report.html, but this replacement only updates the first instance. Use replaceAll / global replacement for repeated placeholders.

Suggested change
.replace('{{REPORT_DATE}}', dateStr)
.replaceAll('{{REPORT_DATE}}', dateStr)

Copilot uses AI. Check for mistakes.
Comment on lines +99 to +103
<tr>
<td>${item.location || 'N/A'}</td>
<td><div class="snippet">${escapeHtml(item.snippet || '')}</div></td>
<td><a href="${item.guidance}" target="_blank">View Guidance</a></td>
</tr>
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTML injection risk: item.location and item.guidance are inserted into the report without escaping/validation. A crafted CSV could inject markup/JS into the generated report. Escape item.location and either strictly validate item.guidance as an allowed URL (e.g., https://learn.microsoft.com/… / go.microsoft.com/fwlink/…) or escape it and render as plain text. Also add rel="noopener noreferrer" when using target="_blank".

Copilot uses AI. Check for mistakes.
> 1. Open the **Data workspace** in Power Pages
> 2. Create a new table (e.g., `contoso_webpage`)
> 3. Add the custom column (e.g., `contoso_pagetype`) to the new table
> 4. Add a lookup column associated with `powerpagescomponent`
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step references powerpagescomponent, but the rest of the skill (and examples below) use powerpagecomponent (no “s”). The inconsistent table name will mislead users during remediation; please correct it to the intended logical name.

Suggested change
> 4. Add a lookup column associated with `powerpagescomponent`
> 4. Add a lookup column associated with `powerpagecomponent`

Copilot uses AI. Check for mistakes.
For each custom column found on an `adx_*` table, instruct the user to:
1. Create a new custom table (e.g., `contoso_webpage`) in the Data workspace
2. Add the custom column (e.g., `contoso_pagetype`) to the new table
3. Add a lookup column associated with `powerpagescomponent`
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This remediation instruction uses powerpagescomponent, but elsewhere in this doc and in SKILL.md the table is referred to as powerpagecomponent. Please fix the inconsistency to avoid pointing users at a non-existent/incorrect table name.

Suggested change
3. Add a lookup column associated with `powerpagescomponent`
3. Add a lookup column associated with `powerpagecomponent`

Copilot uses AI. Check for mistakes.
.replace('{{SITE_NAME}}', escapeHtml(args['site-name'] || 'Unknown'))
.replace('{{WEBSITE_ID}}', escapeHtml(args['website-id'] || 'N/A'))
.replace('{{TEMPLATE_NAME}}', escapeHtml(args['template-name'] || 'Unknown'))
.replace('{{REPORT_DATE}}', new Date().toISOString().split('T')[0])
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The placeholder replacement uses String.prototype.replace, which only replaces the first occurrence. {{REPORT_DATE}} appears twice in the customization report template (metadata + footer), so the footer will keep the raw {{REPORT_DATE}}. Use replaceAll (or a global regex) for placeholders that can appear multiple times.

Suggested change
.replace('{{REPORT_DATE}}', new Date().toISOString().split('T')[0])
.replaceAll('{{REPORT_DATE}}', new Date().toISOString().split('T')[0])

Copilot uses AI. Check for mistakes.
Comment on lines +219 to +223
<div class="phase">
<div class="command-label">Step 3: Download Customization Report</div>
<div class="command-block">pac pages migrate-datamodel --webSiteId "{{WEBSITE_ID}}" --siteCustomizationReportPath "./migration-report"</div>
<div class="result-item success">
<div class="result-title">✓ Success</div>
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pacCommandsHtml hardcodes --webSiteId "{{WEBSITE_ID}}" inside the generated HTML string. Because this placeholder is not part of the outer HTML template, it will never be replaced and will render literally in the final report. Interpolate the actual website id into this string (escaped) or run placeholder substitution on generated sections too.

Copilot uses AI. Check for mistakes.
html += `
<tr>
<td>${item.location || 'N/A'}</td>
<td><div class="snippet">${escapeHtml(item.snippet || '')}</div></td>
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

snippet is computed here but never used, and the generated HTML renders the full item.snippet anyway. This can bloat the report significantly for large snippets and makes the truncation logic dead code. Either use the truncated value in the HTML output or remove the unused variable.

Suggested change
<td><div class="snippet">${escapeHtml(item.snippet || '')}</div></td>
<td><div class="snippet">${escapeHtml(snippet)}</div></td>

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +36
// Parse command line arguments
function parseArgs(args) {
const result = {};
for (let i = 0; i < args.length; i++) {
if (args[i].startsWith('--')) {
const key = args[i].replace('--', '');
const value = args[i + 1];
if (value && !value.startsWith('--')) {
result[key] = value;
i++;
}
}
}
return result;
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR adds a new Node script, but there’s no corresponding node:test coverage. plugins/power-pages/AGENTS.md states that script additions/changes must ship with tests under plugins/power-pages/scripts/tests/. Add a test file that covers CSV parsing + placeholder replacement (including multi-occurrence placeholders) so regressions are caught.

Copilot uses AI. Check for mistakes.
Comment on lines +271 to +279
### CSV Parsing

The script uses `csv-parse` (npm package). Ensure it's available:

```bash
npm install csv-parse
```

Or modify the script to use a different CSV parser if needed.
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc instructs running npm install csv-parse, but the repo doesn’t currently have a Node dependency manifest where this would be captured/installed as part of the skill workflow. Given the script now requires csv-parse/sync, either document the exact supported installation mechanism for this repo (so CI/users get the dependency) or remove the external dependency and update this section accordingly.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants