<# Выгрузка конфигурации 1С в git «Код 1С». Три способа: 1) Релиз типовой из .cf (дистрибутив с releases.1c.ru): .\export-release.ps1 -Repo 1c-code/unf30 -Cf "D:\Дистрибутивы\УНФ\3.0.11.45\1Cv8.cf" 2) Из информационной базы (файловой или серверной), в т.ч. расширение: .\export-release.ps1 -Repo 1c-code/esti -Infobase "D:\Базы\ЭСТИ" .\export-release.ps1 -Repo 1c-code/esti -Infobase "Srvr=srv1c;Ref=esti" -Extension ДоработкиБК -IbUser Админ -IbPassword *** 3) Готовая папка XML-выгрузки (уже выгружена конфигуратором): .\export-release.ps1 -Repo 1c-code/unf30 -FromDump "D:\Выгрузки\УНФ_XML" Тег релиза берётся из версии в Configuration.xml (или -Release). Для расширений — дата и время. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)][string]$Repo, # организация/имя в Forgejo, например 1c-code/unf30 [string]$Cf, [string]$Infobase, [string]$FromDump, [string]$Extension, [string]$IbUser = "", [string]$IbPassword = "", [string]$Release, [string]$GitUrl = "https://git.1sbk.ru", [string]$WorkDir = "C:\kod1c", [string]$Platform # путь к 1cv8.exe; пусто — самая новая установленная ) # Continue: в PowerShell 5.1 вывод git в stderr при Stop прерывает скрипт; ошибки проверяем по $LASTEXITCODE $ErrorActionPreference = "Continue" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 function Step($text) { Write-Host "`n==> $text" -ForegroundColor Green } function Fail($text) { Write-Host "`nОШИБКА: $text" -ForegroundColor Red; exit 1 } $modes = @($Cf, $Infobase, $FromDump) | Where-Object { $_ } if ($modes.Count -ne 1) { Fail "Укажите ровно один источник: -Cf, -Infobase или -FromDump" } if ($Extension -and -not $Infobase) { Fail "Расширение выгружается только из базы: добавьте -Infobase" } if (-not (Get-Command git -ErrorAction SilentlyContinue)) { Fail "Не найден git. Установите Git for Windows: https://git-scm.com/download/win" } function Find-Platform { if ($Platform) { return $Platform } $roots = @("$env:ProgramFiles\1cv8", "${env:ProgramFiles(x86)}\1cv8") | Where-Object { Test-Path $_ } $exe = foreach ($r in $roots) { Get-ChildItem $r -Directory | ForEach-Object { Join-Path $_.FullName "bin\1cv8.exe" } | Where-Object { Test-Path $_ } } $best = $exe | Sort-Object { try { [version](Split-Path (Split-Path (Split-Path $_)) -Leaf) } catch { [version]"0.0" } } | Select-Object -Last 1 if (-not $best) { Fail "Не найдена платформа 1С. Укажите путь: -Platform 'C:\Program Files\1cv8\8.3.xx.xxxx\bin\1cv8.exe'" } return $best } function Run-Designer([string[]]$ibArgs, [string[]]$cmdArgs) { $v8 = Find-Platform $log = Join-Path $env:TEMP ("kod1c-" + [guid]::NewGuid().ToString("N") + ".log") $all = @("DESIGNER") + $ibArgs + $cmdArgs + @("/Out", "`"$log`"", "/DisableStartupDialogs", "/DisableStartupMessages") Write-Host " $v8 $($all -join ' ')" -ForegroundColor DarkGray $p = Start-Process -FilePath $v8 -ArgumentList $all -Wait -PassThru -NoNewWindow $text = if (Test-Path $log) { Get-Content $log -Raw -ErrorAction SilentlyContinue } else { "" } if ($p.ExitCode -ne 0) { Fail "Конфигуратор завершился с кодом $($p.ExitCode).`n$text" } if ($text) { Write-Host $text } } function Ib-Args([string]$ib) { $a = if ($ib -match "Srvr=") { $srv = ($ib -split ";" | Where-Object { $_ -match "^Srvr=" }) -replace "^Srvr=", "" $ref = ($ib -split ";" | Where-Object { $_ -match "^Ref=" }) -replace "^Ref=", "" @("/S", "`"$srv\$ref`"") } else { @("/F", "`"$ib`"") } if ($IbUser) { $a += @("/N", "`"$IbUser`"") } if ($IbPassword) { $a += @("/P", "`"$IbPassword`"") } return $a } # --- 1. Рабочая копия репозитория ------------------------------------------------------------- $name = $Repo.Split("/")[-1] $repoDir = Join-Path $WorkDir "repos\$name" Step "Репозиторий $Repo → $repoDir" New-Item -ItemType Directory -Force -Path (Join-Path $WorkDir "repos") | Out-Null if (-not (Test-Path (Join-Path $repoDir ".git"))) { git clone "$GitUrl/$Repo.git" $repoDir if ($LASTEXITCODE -ne 0) { Fail "Не удалось клонировать $GitUrl/$Repo.git. Проверьте, что репозиторий создан в Forgejo и есть доступ." } } Push-Location $repoDir try { git config core.quotepath off git config core.autocrlf false git config core.longpaths true git fetch --tags --quiet 2>$null $hasCommits = (git rev-parse --verify --quiet HEAD) if ($hasCommits) { git pull --quiet --ff-only } $target = if ($Extension) { Join-Path $repoDir "Extensions\$Extension" } else { Join-Path $repoDir "Configuration" } Step "Очищаю $target (удалённые в новом релизе объекты не должны остаться)" if (Test-Path $target) { Remove-Item $target -Recurse -Force } New-Item -ItemType Directory -Force -Path $target | Out-Null # --- 2. Выгрузка ------------------------------------------------------------------------------ if ($FromDump) { Step "Копирую готовую выгрузку из $FromDump" $src = if (Test-Path (Join-Path $FromDump "Configuration.xml")) { $FromDump } elseif (Test-Path (Join-Path $FromDump "Configuration\Configuration.xml")) { Join-Path $FromDump "Configuration" } else { Fail "В $FromDump нет Configuration.xml — это не XML-выгрузка конфигурации" } robocopy $src $target /E /NFL /NDL /NJH /NJS /NP | Out-Null if ($LASTEXITCODE -ge 8) { Fail "robocopy завершился с кодом $LASTEXITCODE" } } elseif ($Cf) { if (-not (Test-Path $Cf)) { Fail "Файл не найден: $Cf" } $ib = Join-Path $WorkDir "ib\$name" if (-not (Test-Path (Join-Path $ib "1Cv8.1CD"))) { Step "Создаю служебную файловую базу $ib" New-Item -ItemType Directory -Force -Path $ib | Out-Null $p = Start-Process -FilePath (Find-Platform) -ArgumentList @("CREATEINFOBASE", "File=`"$ib`"", "/DisableStartupDialogs") -Wait -PassThru -NoNewWindow if ($p.ExitCode -ne 0) { Fail "Не удалось создать служебную базу" } } Step "Загружаю $Cf в служебную базу" Run-Designer @("/F", "`"$ib`"") @("/LoadCfg", "`"$Cf`"") Step "Выгружаю конфигурацию в файлы" Run-Designer @("/F", "`"$ib`"") @("/DumpConfigToFiles", "`"$target`"", "-Format", "Hierarchical") } else { $extArgs = if ($Extension) { @("-Extension", "`"$Extension`"") } else { @() } Step ("Выгружаю из базы $Infobase" + $(if ($Extension) { ", расширение $Extension" } else { "" })) Run-Designer (Ib-Args $Infobase) (@("/DumpConfigToFiles", "`"$target`"", "-Format", "Hierarchical") + $extArgs) } # служебные файлы конфигуратора, которые не нужны в git Get-ChildItem $target -Recurse -Include "ConfigDumpInfo.xml" -ErrorAction SilentlyContinue | Remove-Item -Force # --- 3. Версия релиза --------------------------------------------------------------------------- $confXml = Join-Path $target "Configuration.xml" if (-not (Test-Path $confXml)) { Fail "После выгрузки нет $confXml — смотрите сообщения конфигуратора выше" } [xml]$x = Get-Content $confXml -Raw -Encoding UTF8 $props = $x.MetaDataObject.Configuration.Properties $version = "$($props.Version)".Trim() $synonym = ($props.Synonym.item | Where-Object { $_.lang -eq "ru" } | Select-Object -First 1).content if (-not $synonym) { $synonym = $props.Name } $stamp = Get-Date -Format "yyyy.MM.dd.HHmm" $tag = if ($Release) { $Release } elseif ($Extension -or -not $version) { $stamp } else { $version } if (git tag --list $tag) { Write-Host "Тег $tag уже есть — добавляю отметку времени" -ForegroundColor Yellow $tag = "$tag-$(Get-Date -Format 'yyyyMMddHHmm')" } # --- 4. Коммит, тег, отправка ----------------------------------------------------------------- Step "Коммит и тег $tag" git add -A $changes = git status --porcelain if (-not $changes) { Write-Host "Изменений нет — эта версия уже в git. Ничего не отправляю." -ForegroundColor Yellow exit 0 } $what = if ($Extension) { "расширение $Extension" } else { "$synonym $version" } git -c user.name="$env:USERNAME" -c user.email="$env:USERNAME@1sbk.ru" commit --quiet -m "$what" git tag -a $tag -m "$what" Step "Отправляю на сервер (первый раз может занять 10–30 минут)" git push --quiet origin HEAD:main if ($LASTEXITCODE -ne 0) { Fail "git push не прошёл" } git push --quiet origin $tag if ($LASTEXITCODE -ne 0) { Fail "git push тега не прошёл" } Write-Host "`nГотово: $Repo, тег $tag. Коннектор проиндексирует релиз в течение 5 минут." -ForegroundColor Green } finally { Pop-Location }