83 خطوط
2.4 KiB
PowerShell
83 خطوط
2.4 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[string] $OutputPath = 'artifacts\crm-release.zip'
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version Latest
|
|
|
|
$root = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
|
$output = if ([System.IO.Path]::IsPathRooted($OutputPath)) {
|
|
[System.IO.Path]::GetFullPath($OutputPath)
|
|
} else {
|
|
[System.IO.Path]::GetFullPath((Join-Path $root $OutputPath))
|
|
}
|
|
|
|
& git -C $root rev-parse --is-inside-work-tree | Out-Null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw 'Release packaging requires a Git worktree.'
|
|
}
|
|
|
|
$status = @(& git -C $root status --porcelain --untracked-files=all)
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw 'Unable to inspect the Git worktree.'
|
|
}
|
|
if ($status.Count -gt 0) {
|
|
throw "The worktree is not clean. Commit the intended release first.`n$($status -join "`n")"
|
|
}
|
|
|
|
$tracked = @(& git -C $root ls-files)
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw 'Unable to list tracked release files.'
|
|
}
|
|
|
|
$forbiddenPathPatterns = @(
|
|
'(^|/)\.env($|\.(?!example$))',
|
|
'(^|/)(vendor|node_modules)(/|$)',
|
|
'(^|/)(storage/logs|bootstrap/cache)(/|$)',
|
|
'\.(sqlite|sqlite3|db)$',
|
|
'(^|/)(auth\.json|cookies[^/]*)$'
|
|
)
|
|
|
|
$forbidden = $tracked | Where-Object {
|
|
$path = $_
|
|
$forbiddenPathPatterns | Where-Object { $path -match $_ } | Select-Object -First 1
|
|
}
|
|
if ($forbidden) {
|
|
throw "Tracked forbidden files would enter the release:`n$($forbidden -join "`n")"
|
|
}
|
|
|
|
$secretPatterns = @(
|
|
'APP_KEY=base64:[A-Za-z0-9+/=]{20,}',
|
|
'(sk|ghp|github_pat)_[A-Za-z0-9_-]{20,}',
|
|
'-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----'
|
|
)
|
|
|
|
foreach ($pattern in $secretPatterns) {
|
|
$matches = @(& git -C $root grep -I -n -E -- $pattern -- . 2>$null)
|
|
if ($pattern.StartsWith('APP_KEY=')) {
|
|
$matches = @($matches | Where-Object { $_ -notmatch 'APP_KEY=base64:A{43}=' })
|
|
}
|
|
if ($LASTEXITCODE -eq 0 -and $matches.Count -gt 0) {
|
|
throw "A possible secret was detected in tracked content:`n$($matches -join "`n")"
|
|
}
|
|
if ($LASTEXITCODE -gt 1) {
|
|
throw 'Secret scan failed.'
|
|
}
|
|
}
|
|
|
|
$outputDirectory = Split-Path -Parent $output
|
|
New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
|
|
if (Test-Path -LiteralPath $output) {
|
|
Remove-Item -LiteralPath $output -Force
|
|
}
|
|
|
|
& git -C $root archive --format=zip --output=$output HEAD
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw 'git archive failed.'
|
|
}
|
|
|
|
$hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $output).Hash
|
|
Write-Host "Release archive: $output"
|
|
Write-Host "SHA256: $hash"
|