feat: integrate N7Cockpit remote mode control
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$OutputDirectory = ''
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
||||
if (-not $OutputDirectory) {
|
||||
$OutputDirectory = Join-Path $projectRoot 'dist'
|
||||
}
|
||||
if (-not [System.IO.Path]::IsPathRooted($OutputDirectory)) {
|
||||
$OutputDirectory = Join-Path $projectRoot $OutputDirectory
|
||||
}
|
||||
$outputRoot = [System.IO.Path]::GetFullPath($OutputDirectory)
|
||||
$projectFull = [System.IO.Path]::GetFullPath($projectRoot)
|
||||
if (-not $outputRoot.StartsWith($projectFull, [StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw 'OutputDirectory must stay inside the N7Cockpit project.'
|
||||
}
|
||||
|
||||
$version = Get-Date -Format 'yyyyMMdd-HHmmss'
|
||||
$stagingRoot = Join-Path $outputRoot "portable-staging-$version"
|
||||
$packageRoot = Join-Path $stagingRoot 'N7Cockpit'
|
||||
$zipPath = Join-Path $outputRoot "N7Cockpit-portable-$version.zip"
|
||||
New-Item -ItemType Directory -Force -Path $packageRoot | Out-Null
|
||||
|
||||
$rootFiles = @(
|
||||
'.gitignore',
|
||||
'build.gradle',
|
||||
'gradle.properties',
|
||||
'gradlew',
|
||||
'gradlew.bat',
|
||||
'README.md',
|
||||
'MIGRATION_GUIDE.md',
|
||||
'settings.gradle'
|
||||
)
|
||||
foreach ($relative in $rootFiles) {
|
||||
Copy-Item -LiteralPath (Join-Path $projectRoot $relative) `
|
||||
-Destination (Join-Path $packageRoot $relative)
|
||||
}
|
||||
|
||||
$directoryPairs = @(
|
||||
@('gradle', 'gradle'),
|
||||
@('app\src', 'app\src')
|
||||
)
|
||||
foreach ($pair in $directoryPairs) {
|
||||
$destination = Join-Path $packageRoot $pair[1]
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $destination) | Out-Null
|
||||
Copy-Item -LiteralPath (Join-Path $projectRoot $pair[0]) `
|
||||
-Destination $destination -Recurse
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $packageRoot 'app') | Out-Null
|
||||
Copy-Item -LiteralPath (Join-Path $projectRoot 'app\build.gradle') `
|
||||
-Destination (Join-Path $packageRoot 'app\build.gradle')
|
||||
Copy-Item -LiteralPath (Join-Path $projectRoot 'app\proguard-rules.pro') `
|
||||
-Destination (Join-Path $packageRoot 'app\proguard-rules.pro')
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $packageRoot 'scripts') | Out-Null
|
||||
$portableScripts = @(
|
||||
'initialize-migration.ps1',
|
||||
'verify-migration-environment.ps1',
|
||||
'check-server-a.ps1',
|
||||
'test-server-a-dry-run.ps1',
|
||||
'build-migrated-apk.ps1',
|
||||
'install-migrated-apk.ps1',
|
||||
'create-portable-package.ps1'
|
||||
)
|
||||
foreach ($script in $portableScripts) {
|
||||
Copy-Item -LiteralPath (Join-Path $projectRoot "scripts\$script") `
|
||||
-Destination (Join-Path $packageRoot "scripts\$script")
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $packageRoot 'config') | Out-Null
|
||||
Copy-Item -LiteralPath (Join-Path $projectRoot 'config\migration.example.psd1') `
|
||||
-Destination (Join-Path $packageRoot 'config\migration.example.psd1')
|
||||
|
||||
$forbiddenNames = @(
|
||||
'migration.psd1',
|
||||
'device-token.txt',
|
||||
'local.properties'
|
||||
)
|
||||
$forbidden = Get-ChildItem -Recurse -Force -File -LiteralPath $packageRoot |
|
||||
Where-Object { $_.Name -in $forbiddenNames -or $_.Extension -in @('.jks', '.p12') }
|
||||
if ($forbidden) {
|
||||
throw "Portable package contains forbidden files: $($forbidden.FullName -join ', ')"
|
||||
}
|
||||
|
||||
$files = Get-ChildItem -Recurse -Force -File -LiteralPath $packageRoot |
|
||||
Sort-Object FullName
|
||||
$manifest = [ordered]@{
|
||||
package = 'N7Cockpit portable source package'
|
||||
generated_at = (Get-Date).ToUniversalTime().ToString('o')
|
||||
contains_credentials = $false
|
||||
default_execution_target = 'dry_run'
|
||||
file_count = $files.Count
|
||||
files = @($files | ForEach-Object {
|
||||
[ordered]@{
|
||||
path = $_.FullName.Substring($packageRoot.Length + 1).Replace('\', '/')
|
||||
size = $_.Length
|
||||
sha256 = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash
|
||||
}
|
||||
})
|
||||
}
|
||||
$manifest | ConvertTo-Json -Depth 5 | Set-Content `
|
||||
-LiteralPath (Join-Path $packageRoot 'PACKAGE-MANIFEST.json') -Encoding UTF8
|
||||
|
||||
Compress-Archive -LiteralPath $packageRoot -DestinationPath $zipPath `
|
||||
-CompressionLevel Optimal
|
||||
$zipHash = (Get-FileHash -LiteralPath $zipPath -Algorithm SHA256).Hash
|
||||
$checksumPath = "$zipPath.sha256"
|
||||
"$zipHash $([System.IO.Path]::GetFileName($zipPath))" | Set-Content `
|
||||
-LiteralPath $checksumPath -Encoding ASCII
|
||||
|
||||
$resolvedStaging = [System.IO.Path]::GetFullPath($stagingRoot)
|
||||
if (-not $resolvedStaging.StartsWith($outputRoot, [StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw 'Refusing to remove staging directory outside output root.'
|
||||
}
|
||||
Remove-Item -LiteralPath $resolvedStaging -Recurse -Force
|
||||
|
||||
[pscustomobject]@{
|
||||
Passed = $true
|
||||
Zip = $zipPath
|
||||
Sha256 = $zipHash
|
||||
ChecksumFile = $checksumPath
|
||||
CredentialFilesIncluded = $false
|
||||
}
|
||||
Reference in New Issue
Block a user