@@ -43,66 +43,78 @@ if (-not $ghCommand) {
4343 exit 1
4444}
4545
46- function gh { & $ghCommand $args }
46+ # Force UTF-8 encoding for pipes to ensure secrets aren't corrupted
47+ $OutputEncoding = [System.Text.Encoding ]::UTF8
4748
48- # Check if logged in
49- gh auth status
50- if ($LASTEXITCODE -ne 0 ) {
51- Write-Error " Error: Not logged into GitHub CLI. Run 'gh auth login' first."
52- exit 1
53- }
49+ # Fix: PowerShell functions don't automatically forward stdin.
50+ # Using $input | ... handles the pipeline gracefully.
51+ function gh { $input | & $ghCommand @args }
5452
5553Write-Host " Reading secrets from $EnvFile ..." - ForegroundColor Cyan
5654
5755$content = Get-Content $EnvFile - Raw
5856$lines = $content -split " `r ?`n "
5957$currentKey = $null
6058$currentValue = @ ()
59+ $isQuoted = $false
6160
6261$secrets = @ {}
6362
6463foreach ($line in $lines ) {
65- # Match a new key-value pair. A key must be at the start of the line,
66- # all uppercase/numbers/underscores, and followed immediately by '='.
67- if ($line -match " ^(?<key>[A-Z0-9_]+)=(?<val>.*)" ) {
64+ # Match a new key-value pair. Handles optional 'export ' prefix.
65+ if ($line -match ' ^\s*(?:export\s+)?(?<key>[A-Z0-9_]+)=(?<val>.*)' ) {
6866 if ($currentKey ) {
6967 # Save previous secret
7068 $secrets [$currentKey ] = ($currentValue -join " `n " ).Trim()
7169 }
7270 $currentKey = $Matches.key
7371 $val = $Matches.val
7472
75- # Check if the value is a single-line quoted value
73+ # Check for quoted multiline start or single-line quoted value
7674 if ($val -match ' ^"(?<inner>.*)"$' ) {
77- $secrets [$currentKey ] = $Matches.inner.Replace (' \"' , ' "' )
78- $currentKey = $null # Mark as done immediately
75+ # Single line quoted: strip quotes and handle escapes
76+ $secrets [$currentKey ] = $Matches.inner.Replace (' \"' , ' "' ).Replace(' \n' , " `n " )
77+ $currentKey = $null
7978 $currentValue = @ ()
79+ } elseif ($val -match ' ^"(?<inner>.*)$' ) {
80+ # Multiline quoted start
81+ $currentValue = @ ($Matches.inner )
82+ $isQuoted = $true
8083 } else {
84+ # Unquoted value
8185 $currentValue = @ ($val )
86+ $isQuoted = $false
8287 }
8388 } elseif ($currentKey ) {
84- # Continue current secret
85- $currentValue += $line
89+ if ($isQuoted -and $line -match ' ^(?<inner>.*)"$' ) {
90+ # End of multiline quoted value
91+ $currentValue += $Matches.inner
92+ $secrets [$currentKey ] = ($currentValue -join " `n " ).Replace(' \"' , ' "' ).Replace(' \n' , " `n " ).Trim()
93+ $currentKey = $null
94+ $currentValue = @ ()
95+ $isQuoted = $false
96+ } else {
97+ # Continue current secret
98+ $currentValue += $line
99+ }
86100 }
87101}
88- # Final secret
102+ # Final secret if not already closed
89103if ($currentKey ) {
90104 $secrets [$currentKey ] = ($currentValue -join " `n " ).Trim()
91105}
92106
93- # Correctly handle multiline quoted values and sync
107+ # Sync secrets
94108foreach ($key in $secrets.Keys ) {
95109 $value = $secrets [$key ]
96110
97- # Final cleanup for multiline quoted strings.
98- # Use (?s) to allow . to match newlines.
99- if ($value -match ' (?s)^"(?<inner>.*)"$' ) {
100- $value = $Matches.inner.Replace (' \"' , ' "' )
101- }
111+ # Validation preview (User requested full view)
112+ $preview = $value.Trim ()
102113
103114 Write-Host " Syncing secret: $key ... ($ ( $value.Length ) bytes)" - ForegroundColor Yellow
115+ Write-Host " Value:`n $preview " - ForegroundColor Gray
104116
105- # Use --body - to read from stdin
117+ # Use --body - to read from stdin. The 'gh' function handles the pipe.
106118 $value | gh secret set $key -- body -
107119
108120 if ($LASTEXITCODE -eq 0 ) {
0 commit comments