Skip to content
Merged
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
210 changes: 122 additions & 88 deletions Prepare-StorePackage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Creates a single universal package for both Chrome Web Store and Edge Add-ons

param(
[string]$Version = '1.1.0',
[string]$Version = '1.2.0',
[string]$OutputPath = 'store-packages'
)

Expand All @@ -16,127 +16,161 @@ if (!(Test-Path $OutputPath)) {
# Determine source directory based on script location
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$sourceDir = $scriptDir # Script is in the root directory
$tempDir = Join-Path $env:TEMP 'check-extension-package'

Write-Host '📦 Preparing universal store package...' -ForegroundColor Yellow
$devFilesToRemove = @(
'*.md',
'*.log',
'.DS_Store',
'Thumbs.db',
'*.tmp'
)

# Clean temp directory
if (Test-Path $tempDir) {
Remove-Item $tempDir -Recurse -Force
function Remove-DevelopmentFiles {
param(
[string]$TargetDir
)

foreach ($pattern in $devFilesToRemove) {
Get-ChildItem $TargetDir -Name $pattern -Recurse -Force 2>$null | ForEach-Object {
$fullPath = Join-Path $TargetDir $_
if (Test-Path $fullPath) {
Remove-Item $fullPath -Force
Write-Host "Removed dev file: $_" -ForegroundColor Gray
}
}
Comment on lines +34 to +40
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Get-ChildItem $TargetDir -Name $pattern ... is not filtering by $pattern: -Name is a switch parameter and the next argument ($pattern) is treated as another -Path, so the dev-file patterns likely won’t be matched/removed. Use -Filter or -Include with -Path $TargetDir -Recurse (and consider using -File and FullName to avoid manual Join-Path).

Suggested change
Get-ChildItem $TargetDir -Name $pattern -Recurse -Force 2>$null | ForEach-Object {
$fullPath = Join-Path $TargetDir $_
if (Test-Path $fullPath) {
Remove-Item $fullPath -Force
Write-Host "Removed dev file: $_" -ForegroundColor Gray
}
}
if ($pattern -like '*`**' -or $pattern -like '*?*') {
Get-ChildItem -Path $TargetDir -Recurse -Force -File -Filter $pattern 2>$null | ForEach-Object {
Remove-Item $_.FullName -Force
Write-Host "Removed dev file: $($_.FullName)" -ForegroundColor Gray
}
}
else {
Get-ChildItem -Path $TargetDir -Recurse -Force -File 2>$null | Where-Object { $_.Name -eq $pattern } | ForEach-Object {
Remove-Item $_.FullName -Force
Write-Host "Removed dev file: $($_.FullName)" -ForegroundColor Gray
}
}

Copilot uses AI. Check for mistakes.
}
}

# Create temp directory
New-Item -ItemType Directory -Path $tempDir | Out-Null
function New-StorePackage {
param(
[string]$Title,
[string]$TempDirName,
[string[]]$FilesToInclude,
[string]$PackageName,
[switch]$RenameFirefoxManifest
)

# Copy only the files needed for the extension
$filesToInclude = @(
'manifest.json',
'blocked.html',
'config',
'images',
'options',
'popup',
'rules',
'scripts',
'styles'
)
$tempDir = Join-Path $env:TEMP $TempDirName
Write-Host "📦 Preparing $Title..." -ForegroundColor Yellow

if (Test-Path $tempDir) {
Remove-Item $tempDir -Recurse -Force
}

foreach ($item in $filesToInclude) {
$sourcePath = Join-Path $sourceDir $item
if (Test-Path $sourcePath) {
$destPath = Join-Path $tempDir $item
if (Test-Path $sourcePath -PathType Container) {
Copy-Item $sourcePath $destPath -Recurse -Force
New-Item -ItemType Directory -Path $tempDir | Out-Null

foreach ($item in $FilesToInclude) {
$sourcePath = Join-Path $sourceDir $item
if (Test-Path $sourcePath) {
$destPath = Join-Path $tempDir $item
if (Test-Path $sourcePath -PathType Container) {
Copy-Item $sourcePath $destPath -Recurse -Force
} else {
Copy-Item $sourcePath $destPath -Force
}
Write-Host "✅ Included: $item" -ForegroundColor Green
} else {
Copy-Item $sourcePath $destPath -Force
Write-Host "⚠️ Not found: $item" -ForegroundColor Yellow
}
Write-Host "✅ Included: $item" -ForegroundColor Green
} else {
Write-Host "⚠️ Not found: $item" -ForegroundColor Yellow
}
Comment on lines +62 to 75
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

If a required file (notably the manifest) is missing, the script only logs a warning and still produces a ZIP, which can lead to invalid store uploads while still reporting success. Consider treating missing required inputs as a terminating error (fail fast) and returning a non-zero exit code.

Copilot uses AI. Check for mistakes.
}

# Remove any development/debug files from copied directories
$devFilesToRemove = @(
'*.md',
'*.log',
'.DS_Store',
'Thumbs.db',
'*.tmp'
)
if ($RenameFirefoxManifest) {
$firefoxManifestPath = Join-Path $tempDir 'manifest.firefox.json'
$standardManifestPath = Join-Path $tempDir 'manifest.json'

foreach ($pattern in $devFilesToRemove) {
Get-ChildItem $tempDir -Name $pattern -Recurse -Force 2>$null | ForEach-Object {
$fullPath = Join-Path $tempDir $_
if (Test-Path $fullPath) {
Remove-Item $fullPath -Force
Write-Host "Removed dev file: $_" -ForegroundColor Gray
if (Test-Path $firefoxManifestPath) {
if (Test-Path $standardManifestPath) {
Remove-Item $standardManifestPath -Force
}
Rename-Item -Path $firefoxManifestPath -NewName 'manifest.json'
Write-Host '✅ Renamed manifest.firefox.json to manifest.json' -ForegroundColor Green
}
}
}

# Update manifest.json for store
$manifestPath = Join-Path $tempDir 'manifest.json'
if (Test-Path $manifestPath) {
$manifest = Get-Content $manifestPath | ConvertFrom-Json
Remove-DevelopmentFiles -TargetDir $tempDir

# Update version
$manifest.version = $Version
$manifestPath = Join-Path $tempDir 'manifest.json'
if (Test-Path $manifestPath) {
$manifest = Get-Content $manifestPath | ConvertFrom-Json
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Get-Content $manifestPath | ConvertFrom-Json will fail for multi-line JSON because the pipeline feeds ConvertFrom-Json one line at a time. Use Get-Content -Raw (or otherwise read the whole file as a single string) before ConvertFrom-Json.

Suggested change
$manifest = Get-Content $manifestPath | ConvertFrom-Json
$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json

Copilot uses AI. Check for mistakes.
$manifest.version = $Version
$manifest.content_security_policy = @{
extension_pages = "script-src 'self'; object-src 'self'"
Comment on lines +96 to +97
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This overwrites content_security_policy with a hard-coded value that drops the existing font-src / style-src allowances currently present in the repo manifests, while extension pages reference Google Fonts (e.g., blocked.html, options/options.html, popup/popup.html). Either preserve the existing CSP directives when updating, or also remove/replace the external font usage so the packaged extension doesn’t break at runtime.

Suggested change
$manifest.content_security_policy = @{
extension_pages = "script-src 'self'; object-src 'self'"
$existingExtensionPagesCsp = $null
if ($null -ne $manifest.content_security_policy) {
if ($manifest.content_security_policy -is [string]) {
$existingExtensionPagesCsp = $manifest.content_security_policy
}
elseif ($null -ne $manifest.content_security_policy.extension_pages) {
$existingExtensionPagesCsp = $manifest.content_security_policy.extension_pages
}
}
if ([string]::IsNullOrWhiteSpace($existingExtensionPagesCsp)) {
$existingExtensionPagesCsp = "script-src 'self'; object-src 'self'"
}
else {
if ($existingExtensionPagesCsp -notmatch "(^|;)\s*script-src\s+'self'(\s*;|$)") {
$existingExtensionPagesCsp = "$existingExtensionPagesCsp; script-src 'self'"
}
if ($existingExtensionPagesCsp -notmatch "(^|;)\s*object-src\s+'self'(\s*;|$)") {
$existingExtensionPagesCsp = "$existingExtensionPagesCsp; object-src 'self'"
}
}
$manifest.content_security_policy = @{
extension_pages = $existingExtensionPagesCsp

Copilot uses AI. Check for mistakes.
}

# Ensure production settings
$manifest.content_security_policy = @{
extension_pages = "script-src 'self'; object-src 'self'"
$jsonString = $manifest | ConvertTo-Json -Depth 10
$jsonString | Set-Content $manifestPath -Encoding UTF8
Write-Host '✅ Updated manifest.json for store publishing' -ForegroundColor Green
}

# Convert back to JSON with proper formatting
$jsonString = $manifest | ConvertTo-Json -Depth 10
$jsonString | Set-Content $manifestPath -Encoding UTF8
$optionsPath = Join-Path $tempDir 'options\options.js'
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Join-Path $tempDir 'options\\options.js' passes a child path containing path separators (and double backslashes), which is brittle and can behave unexpectedly on non-Windows PowerShell. Prefer joining path segments (Join-Path (Join-Path $tempDir 'options') 'options.js') or using a single separator.

Suggested change
$optionsPath = Join-Path $tempDir 'options\options.js'
$optionsPath = Join-Path (Join-Path $tempDir 'options') 'options.js'

Copilot uses AI. Check for mistakes.
if (Test-Path $optionsPath) {
$content = Get-Content $optionsPath -Raw
$content = $content -replace 'const DEVELOPMENT_MODE = true', 'const DEVELOPMENT_MODE = false'
$content | Set-Content $optionsPath -Encoding UTF8
Write-Host '✅ Disabled development mode in options.js' -ForegroundColor Green
}

Comment on lines +105 to 112
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

The “disable development mode” step replaces const DEVELOPMENT_MODE = true, but options/options.js in this repo doesn’t define that constant, so the replacement will be a no-op while still logging success. Either remove this step, or update it to modify the actual dev-mode mechanism used by the options UI (it currently derives isDev from the presence of update_url in the manifest).

Suggested change
$optionsPath = Join-Path $tempDir 'options\options.js'
if (Test-Path $optionsPath) {
$content = Get-Content $optionsPath -Raw
$content = $content -replace 'const DEVELOPMENT_MODE = true', 'const DEVELOPMENT_MODE = false'
$content | Set-Content $optionsPath -Encoding UTF8
Write-Host '✅ Disabled development mode in options.js' -ForegroundColor Green
}

Copilot uses AI. Check for mistakes.
Write-Host '✅ Updated manifest.json for stores' -ForegroundColor Green
}
$packagePath = Join-Path $OutputPath $PackageName
if (Test-Path $packagePath) {
Remove-Item $packagePath -Force
}

# Update options.js to disable development mode
$optionsPath = Join-Path $tempDir 'options\options.js'
if (Test-Path $optionsPath) {
$content = Get-Content $optionsPath -Raw
$content = $content -replace 'const DEVELOPMENT_MODE = true', 'const DEVELOPMENT_MODE = false'
$content | Set-Content $optionsPath -Encoding UTF8
Write-Host '✅ Disabled development mode in options.js' -ForegroundColor Green
}
Compress-Archive -Path "$tempDir\*" -DestinationPath $packagePath
Remove-Item $tempDir -Recurse -Force

# Create the package
$packageName = "check-extension-v$Version.zip"
$packagePath = Join-Path $OutputPath $packageName
$size = [math]::Round((Get-Item $packagePath).Length / 1MB, 2)
Write-Host "✅ Created package: $PackageName ($size MB)" -ForegroundColor Green

# Remove existing package if it exists
if (Test-Path $packagePath) {
Remove-Item $packagePath -Force
return @{
Name = $PackageName
Size = $size
}
}

# Create the zip file
Compress-Archive -Path "$tempDir\*" -DestinationPath $packagePath
Write-Host "✅ Created package: $packageName" -ForegroundColor Green
$baseFilesToInclude = @(
'blocked.html',
'config',
'images',
'options',
'popup',
'rules',
'scripts',
'styles'
)

$universalFilesToInclude = @('manifest.json') + $baseFilesToInclude
$firefoxFilesToInclude = @('manifest.firefox.json') + $baseFilesToInclude

# Clean up temp directory
Remove-Item $tempDir -Recurse -Force
$universalPackage = New-StorePackage `
-Title 'universal Chrome/Edge package' `
-TempDirName 'check-extension-package' `
-FilesToInclude $universalFilesToInclude `
-PackageName "check-extension-v$Version.zip"

# Get file size
$size = [math]::Round((Get-Item $packagePath).Length / 1MB, 2)
$firefoxPackage = New-StorePackage `
-Title 'Firefox package' `
-TempDirName 'check-extension-package-firefox' `
-FilesToInclude $firefoxFilesToInclude `
-PackageName "check-extension-firefox-v$Version.zip" `
-RenameFirefoxManifest

Write-Host ''
Write-Host '🎉 Universal store package created successfully!' -ForegroundColor Green
Write-Host '🎉 Store packages created successfully!' -ForegroundColor Green
Write-Host "📁 Location: $OutputPath" -ForegroundColor Cyan
Write-Host " 📦 $packageName ($size MB)" -ForegroundColor White
Write-Host " 📦 $($universalPackage.Name) ($($universalPackage.Size) MB)" -ForegroundColor White
Write-Host " 🦊 $($firefoxPackage.Name) ($($firefoxPackage.Size) MB)" -ForegroundColor White

Write-Host ''
Write-Host '📋 Next Steps:' -ForegroundColor Yellow
Write-Host '1. Submit the SAME package to both stores:' -ForegroundColor White
Write-Host '1. Submit Chrome/Edge package to their stores:' -ForegroundColor White
Write-Host ' 📤 Chrome Web Store: https://chrome.google.com/webstore/devconsole' -ForegroundColor Cyan
Write-Host ' 📤 Edge Add-ons: https://partner.microsoft.com/dashboard/microsoftedge' -ForegroundColor Cyan
Write-Host '2. Note the assigned extension IDs from each store' -ForegroundColor White
Write-Host '3. Update enterprise registry files with store IDs:' -ForegroundColor White
Write-Host '2. Submit Firefox package to AMO:' -ForegroundColor White
Write-Host ' 🦊 Firefox Add-ons: https://addons.mozilla.org/developers/' -ForegroundColor Cyan
Write-Host '3. Note the assigned extension IDs from each store' -ForegroundColor White
Write-Host '4. Update enterprise registry files with store IDs:' -ForegroundColor White
Write-Host ' .\Update-StoreIDs.ps1 -ChromeID <chrome-id> -EdgeID <edge-id>' -ForegroundColor Gray
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

The “Next Steps” command uses -ChromeID / -EdgeID, but Update-StoreIDs.ps1 defines parameters -ChromeExtensionId, -EdgeExtensionId, and -FirefoxExtensionId. Update this output so users can copy/paste a working command.

Suggested change
Write-Host ' .\Update-StoreIDs.ps1 -ChromeID <chrome-id> -EdgeID <edge-id>' -ForegroundColor Gray
Write-Host ' .\Update-StoreIDs.ps1 -ChromeExtensionId <chrome-id> -EdgeExtensionId <edge-id> -FirefoxExtensionId <firefox-id>' -ForegroundColor Gray

Copilot uses AI. Check for mistakes.
Write-Host '4. Test managed policies with store-installed extensions' -ForegroundColor White
Write-Host '5. Test managed policies with store-installed extensions' -ForegroundColor White

Write-Host ''
Write-Host '💡 Remember: Both stores accept the same ZIP file!' -ForegroundColor Yellow
Write-Host '💡 Remember: Firefox uses the dedicated Firefox ZIP from this script.' -ForegroundColor Yellow
Loading